From: Fabien Potencier Date: Tue, 11 May 2010 08:38:48 +0000 (+0200) Subject: changed coding standards X-Git-Url: http://git.silmor.de/gitweb/?a=commitdiff_plain;h=4d8fc51112ba6df760ab2eba5db51e00cfd5c17d;p=konrad%2Ftwig.git changed coding standards --- diff --git a/bin/create_pear_package.php b/bin/create_pear_package.php index 0ed7a89..4899927 100644 --- a/bin/create_pear_package.php +++ b/bin/create_pear_package.php @@ -2,32 +2,32 @@ if (!isset($argv[1])) { - die('You must provide the version (1.0.0)'); + die('You must provide the version (1.0.0)'); } if (!isset($argv[2])) { - die('You must provide the stability (alpha, beta, or stable)'); + die('You must provide the stability (alpha, beta, or stable)'); } $context = array( - 'date' => date('Y-m-d'), - 'time' => date('H:m:00'), - 'version' => $argv[1], - 'api_version' => $argv[1], - 'stability' => $argv[2], - 'api_stability' => $argv[2], + 'date' => date('Y-m-d'), + 'time' => date('H:m:00'), + 'version' => $argv[1], + 'api_version' => $argv[1], + 'stability' => $argv[2], + 'api_stability' => $argv[2], ); $context['files'] = ''; $path = realpath(dirname(__FILE__).'/../lib/Twig'); foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path), RecursiveIteratorIterator::LEAVES_ONLY) as $file) { - if (preg_match('/\.php$/', $file)) - { - $name = str_replace($path.'/', '', $file); - $context['files'] .= ' '."\n"; - } + if (preg_match('/\.php$/', $file)) + { + $name = str_replace($path.'/', '', $file); + $context['files'] .= ' '."\n"; + } } $template = file_get_contents(dirname(__FILE__).'/../package.xml.tpl'); @@ -36,7 +36,7 @@ file_put_contents(dirname(__FILE__).'/../package.xml', $content); function replace_parameters($matches) { - global $context; + global $context; - return isset($context[$matches[1]]) ? $context[$matches[1]] : null; + return isset($context[$matches[1]]) ? $context[$matches[1]] : null; } diff --git a/lib/Twig/Autoloader.php b/lib/Twig/Autoloader.php index a3b30ec..ec0ffac 100644 --- a/lib/Twig/Autoloader.php +++ b/lib/Twig/Autoloader.php @@ -18,31 +18,30 @@ */ class Twig_Autoloader { - /** - * Registers Twig_Autoloader as an SPL autoloader. - */ - static public function register() - { - ini_set('unserialize_callback_func', 'spl_autoload_call'); - spl_autoload_register(array(new self, 'autoload')); - } - - /** - * Handles autoloading of classes. - * - * @param string $class A class name. - * - * @return boolean Returns true if the class has been loaded - */ - static public function autoload($class) - { - if (0 !== strpos($class, 'Twig')) + /** + * Registers Twig_Autoloader as an SPL autoloader. + */ + static public function register() { - return false; + ini_set('unserialize_callback_func', 'spl_autoload_call'); + spl_autoload_register(array(new self, 'autoload')); } - require dirname(__FILE__).'/../'.str_replace('_', '/', $class).'.php'; + /** + * Handles autoloading of classes. + * + * @param string $class A class name. + * + * @return boolean Returns true if the class has been loaded + */ + static public function autoload($class) + { + if (0 !== strpos($class, 'Twig')) { + return false; + } + + require dirname(__FILE__).'/../'.str_replace('_', '/', $class).'.php'; - return true; - } + return true; + } } diff --git a/lib/Twig/Compiler.php b/lib/Twig/Compiler.php index 720f9b0..960e98f 100644 --- a/lib/Twig/Compiler.php +++ b/lib/Twig/Compiler.php @@ -19,233 +19,220 @@ */ class Twig_Compiler implements Twig_CompilerInterface { - protected $lastLine; - protected $source; - protected $indentation; - protected $env; - - /** - * Constructor. - * - * @param Twig_Environment $env The twig environment instance - */ - public function __construct(Twig_Environment $env = null) - { - $this->env = $env; - } - - public function setEnvironment(Twig_Environment $env) - { - $this->env = $env; - } - - /** - * Gets the current PHP code after compilation. - * - * @return string The PHP code - */ - public function getSource() - { - return $this->source; - } - - /** - * Compiles a node. - * - * @param Twig_Node $node The node to compile - * - * @return Twig_Compiler The current compiler instance - */ - public function compile(Twig_Node $node) - { - $this->lastLine = null; - $this->source = ''; - $this->indentation = 0; - - $node->compile($this); - - return $this; - } - - public function subcompile(Twig_Node $node) - { - $node->compile($this); - - return $this; - } - - /** - * Adds a raw string to the compiled code. - * - * @param string $string The string - * - * @return Twig_Compiler The current compiler instance - */ - public function raw($string) - { - $this->source .= $string; - - return $this; - } - - /** - * Writes a string to the compiled code by adding indentation. - * - * @return Twig_Compiler The current compiler instance - */ - public function write() - { - $strings = func_get_args(); - foreach ($strings as $string) - { - $this->source .= str_repeat(' ', $this->indentation * 2).$string; - } - - return $this; - } - - /** - * Adds a quoted string to the compiled code. - * - * @param string $string The string - * - * @return Twig_Compiler The current compiler instance - */ - public function string($value) - { - $this->source .= sprintf('"%s"', addcslashes($value, "\t\"\$\\")); - - return $this; - } - - /** - * Returns a PHP representation of a given value. - * - * @param mixed $value The value to convert - * - * @return Twig_Compiler The current compiler instance - */ - public function repr($value) - { - if (is_int($value) || is_float($value)) - { - $this->raw($value); - } - else if (is_null($value)) - { - $this->raw('null'); - } - else if (is_bool($value)) - { - $this->raw($value ? 'true' : 'false'); - } - else if (is_array($value)) - { - $this->raw('array('); - $i = 0; - foreach ($value as $key => $value) - { - if ($i++) - { - $this->raw(', '); + protected $lastLine; + protected $source; + protected $indentation; + protected $env; + + /** + * Constructor. + * + * @param Twig_Environment $env The twig environment instance + */ + public function __construct(Twig_Environment $env = null) + { + $this->env = $env; + } + + public function setEnvironment(Twig_Environment $env) + { + $this->env = $env; + } + + /** + * Gets the current PHP code after compilation. + * + * @return string The PHP code + */ + public function getSource() + { + return $this->source; + } + + /** + * Compiles a node. + * + * @param Twig_Node $node The node to compile + * + * @return Twig_Compiler The current compiler instance + */ + public function compile(Twig_Node $node) + { + $this->lastLine = null; + $this->source = ''; + $this->indentation = 0; + + $node->compile($this); + + return $this; + } + + public function subcompile(Twig_Node $node) + { + $node->compile($this); + + return $this; + } + + /** + * Adds a raw string to the compiled code. + * + * @param string $string The string + * + * @return Twig_Compiler The current compiler instance + */ + public function raw($string) + { + $this->source .= $string; + + return $this; + } + + /** + * Writes a string to the compiled code by adding indentation. + * + * @return Twig_Compiler The current compiler instance + */ + public function write() + { + $strings = func_get_args(); + foreach ($strings as $string) { + $this->source .= str_repeat(' ', $this->indentation * 2).$string; } - $this->repr($key); - $this->raw(' => '); - $this->repr($value); - } - $this->raw(')'); - } - else - { - $this->string($value); - } - - return $this; - } - - /** - * Pushes the current context on the stack. - * - * @return Twig_Compiler The current compiler instance - */ - public function pushContext() - { - // the (array) cast bypasses a PHP 5.2.6 bug - $this->write('$context[\'_parent\'] = (array) $context;'."\n"); - - return $this; - } - - /** - * Pops a context from the stack. - * - * @return Twig_Compiler The current compiler instance - */ - public function popContext() - { - $this->write('$context = $context[\'_parent\'];'."\n"); - - return $this; - } - - /** - * Adds debugging information. - * - * @param Twig_Node $node The related twig node - * - * @return Twig_Compiler The current compiler instance - */ - public function addDebugInfo(Twig_Node $node) - { - if ($node->getLine() != $this->lastLine) - { - $this->lastLine = $node->getLine(); - $this->write("// line {$node->getLine()}\n"); - } - - return $this; - } - - /** - * Indents the generated code. - * - * @param integer $indent The number of indentation to add - * - * @return Twig_Compiler The current compiler instance - */ - public function indent($step = 1) - { - $this->indentation += $step; - - return $this; - } - - /** - * Outdents the generated code. - * - * @param integer $indent The number of indentation to remove - * - * @return Twig_Compiler The current compiler instance - */ - public function outdent($step = 1) - { - $this->indentation -= $step; - - return $this; - } - - /** - * Returns the environment instance related to this compiler. - * - * @return Twig_Environment The environment instance - */ - public function getEnvironment() - { - return $this->env; - } - - public function getTemplateClass($name) - { - return $this->getEnvironment()->getTemplateClass($name); - } + + return $this; + } + + /** + * Adds a quoted string to the compiled code. + * + * @param string $string The string + * + * @return Twig_Compiler The current compiler instance + */ + public function string($value) + { + $this->source .= sprintf('"%s"', addcslashes($value, "\t\"\$\\")); + + return $this; + } + + /** + * Returns a PHP representation of a given value. + * + * @param mixed $value The value to convert + * + * @return Twig_Compiler The current compiler instance + */ + public function repr($value) + { + if (is_int($value) || is_float($value)) { + $this->raw($value); + } else if (is_null($value)) { + $this->raw('null'); + } else if (is_bool($value)) { + $this->raw($value ? 'true' : 'false'); + } else if (is_array($value)) { + $this->raw('array('); + $i = 0; + foreach ($value as $key => $value) { + if ($i++) { + $this->raw(', '); + } + $this->repr($key); + $this->raw(' => '); + $this->repr($value); + } + $this->raw(')'); + } else { + $this->string($value); + } + + return $this; + } + + /** + * Pushes the current context on the stack. + * + * @return Twig_Compiler The current compiler instance + */ + public function pushContext() + { + // the (array) cast bypasses a PHP 5.2.6 bug + $this->write('$context[\'_parent\'] = (array) $context;'."\n"); + + return $this; + } + + /** + * Pops a context from the stack. + * + * @return Twig_Compiler The current compiler instance + */ + public function popContext() + { + $this->write('$context = $context[\'_parent\'];'."\n"); + + return $this; + } + + /** + * Adds debugging information. + * + * @param Twig_Node $node The related twig node + * + * @return Twig_Compiler The current compiler instance + */ + public function addDebugInfo(Twig_Node $node) + { + if ($node->getLine() != $this->lastLine) { + $this->lastLine = $node->getLine(); + $this->write("// line {$node->getLine()}\n"); + } + + return $this; + } + + /** + * Indents the generated code. + * + * @param integer $indent The number of indentation to add + * + * @return Twig_Compiler The current compiler instance + */ + public function indent($step = 1) + { + $this->indentation += $step; + + return $this; + } + + /** + * Outdents the generated code. + * + * @param integer $indent The number of indentation to remove + * + * @return Twig_Compiler The current compiler instance + */ + public function outdent($step = 1) + { + $this->indentation -= $step; + + return $this; + } + + /** + * Returns the environment instance related to this compiler. + * + * @return Twig_Environment The environment instance + */ + public function getEnvironment() + { + return $this->env; + } + + public function getTemplateClass($name) + { + return $this->getEnvironment()->getTemplateClass($name); + } } diff --git a/lib/Twig/CompilerInterface.php b/lib/Twig/CompilerInterface.php index 365b59f..7d1ad8a 100644 --- a/lib/Twig/CompilerInterface.php +++ b/lib/Twig/CompilerInterface.php @@ -18,19 +18,19 @@ */ interface Twig_CompilerInterface { - /** - * Compiles a node. - * - * @param Twig_Node $node The node to compile - * - * @return Twig_Compiler The current compiler instance - */ - public function compile(Twig_Node $node); + /** + * Compiles a node. + * + * @param Twig_Node $node The node to compile + * + * @return Twig_Compiler The current compiler instance + */ + public function compile(Twig_Node $node); - /** - * Gets the current PHP code after compilation. - * - * @return string The PHP code - */ - public function getSource(); + /** + * Gets the current PHP code after compilation. + * + * @return string The PHP code + */ + public function getSource(); } diff --git a/lib/Twig/Environment.php b/lib/Twig/Environment.php index 7ec122c..488557e 100644 --- a/lib/Twig/Environment.php +++ b/lib/Twig/Environment.php @@ -11,373 +11,348 @@ class Twig_Environment { - const VERSION = '0.9.6-DEV'; - - protected $charset; - protected $loader; - protected $trimBlocks; - protected $debug; - protected $autoReload; - protected $cache; - protected $lexer; - protected $parser; - protected $compiler; - protected $baseTemplateClass; - protected $extensions; - protected $parsers; - protected $visitors; - protected $filters; - protected $runtimeInitialized; - protected $loadedTemplates; - - /** - * Constructor. - * - * Available options: - * - * * debug: When set to `true`, the generated templates have a __toString() - * method that you can use to display the generated nodes (default to - * false). - * - * * trim_blocks: Mimicks the behavior of PHP by removing the newline that - * follows instructions if present (default to false). - * - * * charset: The charset used by the templates (default to utf-8). - * - * * base_template_class: The base template class to use for generated - * templates (default to Twig_Template). - * - * * cache: Can be one of three values: - * * null (the default): Twig will create a sub-directory under the system tmp directory - * (not recommended as templates from two projects with the same name will share the cache) - * * false: disable the compile cache altogether - * * An absolute path where to store the compiled templates - * - * * auto_reload: Whether to reload the template is the original source changed. - * If you don't provide the auto_reload option, it will be - * determined automatically base on the debug value. - */ - public function __construct(Twig_LoaderInterface $loader = null, $options = array()) - { - if (null !== $loader) - { - $this->setLoader($loader); - } - - $this->debug = isset($options['debug']) ? (bool) $options['debug'] : false; - $this->trimBlocks = isset($options['trim_blocks']) ? (bool) $options['trim_blocks'] : false; - $this->charset = isset($options['charset']) ? $options['charset'] : 'UTF-8'; - $this->baseTemplateClass = isset($options['base_template_class']) ? $options['base_template_class'] : 'Twig_Template'; - $this->autoReload = isset($options['auto_reload']) ? (bool) $options['auto_reload'] : $this->debug; - $this->extensions = array('core' => new Twig_Extension_Core()); - $this->runtimeInitialized = false; - $this->setCache(isset($options['cache']) ? $options['cache'] : null); - } - - public function getBaseTemplateClass() - { - return $this->baseTemplateClass; - } - - public function setBaseTemplateClass($class) - { - $this->baseTemplateClass = $class; - } - - public function enableDebug() - { - $this->debug = true; - } - - public function disableDebug() - { - $this->debug = false; - } - - public function isDebug() - { - return $this->debug; - } - - public function isAutoReload() - { - return $this->autoReload; - } - - public function setAutoReload($autoReload) - { - $this->autoReload = (Boolean) $autoReload; - } - - public function getCache() - { - return $this->cache; - } - - public function setCache($cache) - { - $this->cache = null === $cache ? sys_get_temp_dir().DIRECTORY_SEPARATOR.'twig_'.md5(dirname(__FILE__)) : $cache; - - if (false !== $this->cache && !is_dir($this->cache)) - { - mkdir($this->cache, 0755, true); - } - } - - public function getCacheFilename($name) - { - return $this->getCache() ? $this->getCache().'/'.$this->getTemplateClass($name).'.php' : false; - } - - public function getTrimBlocks() - { - return $this->trimBlocks; - } - - public function setTrimBlocks($bool) - { - $this->trimBlocks = (bool) $bool; - } - - /** - * Gets the template class associated with the given string. - * - * @param string $name The name for which to calculate the template class name - * - * @return string The template class name - */ - public function getTemplateClass($name) - { - return '__TwigTemplate_'.md5($this->loader->getCacheKey($name)); - } - - /** - * Loads a template by name. - * - * @param string $name The template name - * - * @return Twig_TemplateInterface A template instance representing the given template name - */ - public function loadTemplate($name) - { - $cls = $this->getTemplateClass($name); - - if (isset($this->loadedTemplates[$cls])) - { - return $this->loadedTemplates[$cls]; - } - - if (!class_exists($cls, false)) - { - if (false === $cache = $this->getCacheFilename($name)) - { - eval('?>'.$this->compileSource($this->loader->getSource($name), $name)); - } - else - { - if (!file_exists($cache) || ($this->isAutoReload() && !$this->loader->isFresh($name, filemtime($cache)))) - { - $content = $this->compileSource($this->loader->getSource($name), $name); - - if (false === file_put_contents($cache, $content, LOCK_EX)) - { - eval('?>'.$content); - } - else - { - require_once $cache; - } - } - else - { - require_once $cache; + const VERSION = '0.9.6-DEV'; + + protected $charset; + protected $loader; + protected $trimBlocks; + protected $debug; + protected $autoReload; + protected $cache; + protected $lexer; + protected $parser; + protected $compiler; + protected $baseTemplateClass; + protected $extensions; + protected $parsers; + protected $visitors; + protected $filters; + protected $runtimeInitialized; + protected $loadedTemplates; + + /** + * Constructor. + * + * Available options: + * + * * debug: When set to `true`, the generated templates have a __toString() + * method that you can use to display the generated nodes (default to + * false). + * + * * trim_blocks: Mimicks the behavior of PHP by removing the newline that + * follows instructions if present (default to false). + * + * * charset: The charset used by the templates (default to utf-8). + * + * * base_template_class: The base template class to use for generated + * templates (default to Twig_Template). + * + * * cache: Can be one of three values: + * * null (the default): Twig will create a sub-directory under the system tmp directory + * (not recommended as templates from two projects with the same name will share the cache) + * * false: disable the compile cache altogether + * * An absolute path where to store the compiled templates + * + * * auto_reload: Whether to reload the template is the original source changed. + * If you don't provide the auto_reload option, it will be + * determined automatically base on the debug value. + */ + public function __construct(Twig_LoaderInterface $loader = null, $options = array()) + { + if (null !== $loader) { + $this->setLoader($loader); } - } + + $this->debug = isset($options['debug']) ? (bool) $options['debug'] : false; + $this->trimBlocks = isset($options['trim_blocks']) ? (bool) $options['trim_blocks'] : false; + $this->charset = isset($options['charset']) ? $options['charset'] : 'UTF-8'; + $this->baseTemplateClass = isset($options['base_template_class']) ? $options['base_template_class'] : 'Twig_Template'; + $this->autoReload = isset($options['auto_reload']) ? (bool) $options['auto_reload'] : $this->debug; + $this->extensions = array('core' => new Twig_Extension_Core()); + $this->runtimeInitialized = false; + $this->setCache(isset($options['cache']) ? $options['cache'] : null); + } + + public function getBaseTemplateClass() + { + return $this->baseTemplateClass; + } + + public function setBaseTemplateClass($class) + { + $this->baseTemplateClass = $class; + } + + public function enableDebug() + { + $this->debug = true; + } + + public function disableDebug() + { + $this->debug = false; + } + + public function isDebug() + { + return $this->debug; + } + + public function isAutoReload() + { + return $this->autoReload; + } + + public function setAutoReload($autoReload) + { + $this->autoReload = (Boolean) $autoReload; + } + + public function getCache() + { + return $this->cache; } - if (!$this->runtimeInitialized) + public function setCache($cache) { - $this->initRuntime(); + $this->cache = null === $cache ? sys_get_temp_dir().DIRECTORY_SEPARATOR.'twig_'.md5(dirname(__FILE__)) : $cache; - $this->runtimeInitialized = true; + if (false !== $this->cache && !is_dir($this->cache)) { + mkdir($this->cache, 0755, true); + } } - return $this->loadedTemplates[$cls] = new $cls($this); - } + public function getCacheFilename($name) + { + return $this->getCache() ? $this->getCache().'/'.$this->getTemplateClass($name).'.php' : false; + } - public function clearTemplateCache() - { - $this->loadedTemplates = array(); - } + public function getTrimBlocks() + { + return $this->trimBlocks; + } - public function getLexer() - { - if (null === $this->lexer) + public function setTrimBlocks($bool) { - $this->lexer = new Twig_Lexer($this); + $this->trimBlocks = (bool) $bool; } - return $this->lexer; - } + /** + * Gets the template class associated with the given string. + * + * @param string $name The name for which to calculate the template class name + * + * @return string The template class name + */ + public function getTemplateClass($name) + { + return '__TwigTemplate_'.md5($this->loader->getCacheKey($name)); + } - public function setLexer(Twig_LexerInterface $lexer) - { - $this->lexer = $lexer; - $lexer->setEnvironment($this); - } + /** + * Loads a template by name. + * + * @param string $name The template name + * + * @return Twig_TemplateInterface A template instance representing the given template name + */ + public function loadTemplate($name) + { + $cls = $this->getTemplateClass($name); - public function tokenize($source, $name) - { - return $this->getLexer()->tokenize($source, $name); - } + if (isset($this->loadedTemplates[$cls])) { + return $this->loadedTemplates[$cls]; + } + + if (!class_exists($cls, false)) { + if (false === $cache = $this->getCacheFilename($name)) { + eval('?>'.$this->compileSource($this->loader->getSource($name), $name)); + } else { + if (!file_exists($cache) || ($this->isAutoReload() && !$this->loader->isFresh($name, filemtime($cache)))) { + $content = $this->compileSource($this->loader->getSource($name), $name); + + if (false === file_put_contents($cache, $content, LOCK_EX)) { + eval('?>'.$content); + } else { + require_once $cache; + } + } else { + require_once $cache; + } + } + } + + if (!$this->runtimeInitialized) { + $this->initRuntime(); + + $this->runtimeInitialized = true; + } - public function getParser() - { - if (null === $this->parser) + return $this->loadedTemplates[$cls] = new $cls($this); + } + + public function clearTemplateCache() { - $this->parser = new Twig_Parser($this); + $this->loadedTemplates = array(); } - return $this->parser; - } + public function getLexer() + { + if (null === $this->lexer) { + $this->lexer = new Twig_Lexer($this); + } + + return $this->lexer; + } - public function setParser(Twig_ParserInterface $parser) - { - $this->parser = $parser; - $parser->setEnvironment($this); - } + public function setLexer(Twig_LexerInterface $lexer) + { + $this->lexer = $lexer; + $lexer->setEnvironment($this); + } - public function parse(Twig_TokenStream $tokens) - { - return $this->getParser()->parse($tokens); - } + public function tokenize($source, $name) + { + return $this->getLexer()->tokenize($source, $name); + } - public function getCompiler() - { - if (null === $this->compiler) + public function getParser() { - $this->compiler = new Twig_Compiler($this); + if (null === $this->parser) { + $this->parser = new Twig_Parser($this); + } + + return $this->parser; } - return $this->compiler; - } + public function setParser(Twig_ParserInterface $parser) + { + $this->parser = $parser; + $parser->setEnvironment($this); + } - public function setCompiler(Twig_CompilerInterface $compiler) - { - $this->compiler = $compiler; - $compiler->setEnvironment($this); - } + public function parse(Twig_TokenStream $tokens) + { + return $this->getParser()->parse($tokens); + } - public function compile(Twig_Node $node) - { - return $this->getCompiler()->compile($node)->getSource(); - } + public function getCompiler() + { + if (null === $this->compiler) { + $this->compiler = new Twig_Compiler($this); + } - public function compileSource($source, $name) - { - return $this->compile($this->parse($this->tokenize($source, $name))); - } + return $this->compiler; + } - public function setLoader(Twig_LoaderInterface $loader) - { - $this->loader = $loader; - } + public function setCompiler(Twig_CompilerInterface $compiler) + { + $this->compiler = $compiler; + $compiler->setEnvironment($this); + } - public function getLoader() - { - return $this->loader; - } + public function compile(Twig_Node $node) + { + return $this->getCompiler()->compile($node)->getSource(); + } - public function setCharset($charset) - { - $this->charset = $charset; - } + public function compileSource($source, $name) + { + return $this->compile($this->parse($this->tokenize($source, $name))); + } - public function getCharset() - { - return $this->charset; - } + public function setLoader(Twig_LoaderInterface $loader) + { + $this->loader = $loader; + } - public function initRuntime() - { - foreach ($this->getExtensions() as $extension) + public function getLoader() { - $extension->initRuntime(); + return $this->loader; } - } - public function hasExtension($name) - { - return isset($this->extensions[$name]); - } + public function setCharset($charset) + { + $this->charset = $charset; + } - public function getExtension($name) - { - return $this->extensions[$name]; - } + public function getCharset() + { + return $this->charset; + } - public function addExtension(Twig_ExtensionInterface $extension) - { - $this->extensions[$extension->getName()] = $extension; - } + public function initRuntime() + { + foreach ($this->getExtensions() as $extension) { + $extension->initRuntime(); + } + } - public function removeExtension($name) - { - unset($this->extensions[$name]); - } + public function hasExtension($name) + { + return isset($this->extensions[$name]); + } - public function setExtensions(array $extensions) - { - foreach ($extensions as $extension) + public function getExtension($name) { - $this->addExtension($extension); + return $this->extensions[$name]; } - } - public function getExtensions() - { - return $this->extensions; - } + public function addExtension(Twig_ExtensionInterface $extension) + { + $this->extensions[$extension->getName()] = $extension; + } - public function getTokenParsers() - { - if (null === $this->parsers) + public function removeExtension($name) { - $this->parsers = array(); - foreach ($this->getExtensions() as $extension) - { - $this->parsers = array_merge($this->parsers, $extension->getTokenParsers()); - } + unset($this->extensions[$name]); } - return $this->parsers; - } + public function setExtensions(array $extensions) + { + foreach ($extensions as $extension) { + $this->addExtension($extension); + } + } - public function getNodeVisitors() - { - if (null === $this->visitors) + public function getExtensions() { - $this->visitors = array(); - foreach ($this->getExtensions() as $extension) - { - $this->visitors = array_merge($this->visitors, $extension->getNodeVisitors()); - } + return $this->extensions; } - return $this->visitors; - } + public function getTokenParsers() + { + if (null === $this->parsers) { + $this->parsers = array(); + foreach ($this->getExtensions() as $extension) { + $this->parsers = array_merge($this->parsers, $extension->getTokenParsers()); + } + } + + return $this->parsers; + } - public function getFilters() - { - if (null === $this->filters) + public function getNodeVisitors() { - $this->filters = array(); - foreach ($this->getExtensions() as $extension) - { - $this->filters = array_merge($this->filters, $extension->getFilters()); - } + if (null === $this->visitors) { + $this->visitors = array(); + foreach ($this->getExtensions() as $extension) { + $this->visitors = array_merge($this->visitors, $extension->getNodeVisitors()); + } + } + + return $this->visitors; } - return $this->filters; - } + public function getFilters() + { + if (null === $this->filters) { + $this->filters = array(); + foreach ($this->getExtensions() as $extension) { + $this->filters = array_merge($this->filters, $extension->getFilters()); + } + } + + return $this->filters; + } } diff --git a/lib/Twig/ExpressionParser.php b/lib/Twig/ExpressionParser.php index 20b6f34..1152706 100644 --- a/lib/Twig/ExpressionParser.php +++ b/lib/Twig/ExpressionParser.php @@ -19,518 +19,470 @@ */ class Twig_ExpressionParser { - protected $parser; - - public function __construct(Twig_Parser $parser) - { - $this->parser = $parser; - } - - public function parseExpression() - { - return $this->parseConditionalExpression(); - } - - public function parseConditionalExpression() - { - $lineno = $this->parser->getCurrentToken()->getLine(); - $expr1 = $this->parseOrExpression(); - while ($this->parser->getStream()->test(Twig_Token::OPERATOR_TYPE, '?')) - { - $this->parser->getStream()->next(); - $expr2 = $this->parseOrExpression(); - $this->parser->getStream()->expect(Twig_Token::OPERATOR_TYPE, ':'); - $expr3 = $this->parseConditionalExpression(); - $expr1 = new Twig_Node_Expression_Conditional($expr1, $expr2, $expr3, $lineno); - $lineno = $this->parser->getCurrentToken()->getLine(); - } - - return $expr1; - } + protected $parser; - public function parseOrExpression() - { - $lineno = $this->parser->getCurrentToken()->getLine(); - $left = $this->parseAndExpression(); - while ($this->parser->getStream()->test('or')) + public function __construct(Twig_Parser $parser) { - $this->parser->getStream()->next(); - $right = $this->parseAndExpression(); - $left = new Twig_Node_Expression_Binary_Or($left, $right, $lineno); - $lineno = $this->parser->getCurrentToken()->getLine(); + $this->parser = $parser; } - return $left; - } - - public function parseAndExpression() - { - $lineno = $this->parser->getCurrentToken()->getLine(); - $left = $this->parseCompareExpression(); - while ($this->parser->getStream()->test('and')) + public function parseExpression() { - $this->parser->getStream()->next(); - $right = $this->parseCompareExpression(); - $left = new Twig_Node_Expression_Binary_And($left, $right, $lineno); - $lineno = $this->parser->getCurrentToken()->getLine(); + return $this->parseConditionalExpression(); } - return $left; - } - - public function parseCompareExpression() - { - static $operators = array('==', '!=', '<', '>', '>=', '<='); - $lineno = $this->parser->getCurrentToken()->getLine(); - $expr = $this->parseAddExpression(); - $ops = array(); - while ( - $this->parser->getStream()->test(Twig_Token::OPERATOR_TYPE, $operators) - || - $this->parser->getStream()->test(Twig_Token::NAME_TYPE, 'in') - ) + public function parseConditionalExpression() { - $ops[] = array($this->parser->getStream()->next()->getValue(), $this->parseAddExpression()); + $lineno = $this->parser->getCurrentToken()->getLine(); + $expr1 = $this->parseOrExpression(); + while ($this->parser->getStream()->test(Twig_Token::OPERATOR_TYPE, '?')) { + $this->parser->getStream()->next(); + $expr2 = $this->parseOrExpression(); + $this->parser->getStream()->expect(Twig_Token::OPERATOR_TYPE, ':'); + $expr3 = $this->parseConditionalExpression(); + $expr1 = new Twig_Node_Expression_Conditional($expr1, $expr2, $expr3, $lineno); + $lineno = $this->parser->getCurrentToken()->getLine(); + } + + return $expr1; } - if (empty($ops)) + public function parseOrExpression() { - return $expr; - } + $lineno = $this->parser->getCurrentToken()->getLine(); + $left = $this->parseAndExpression(); + while ($this->parser->getStream()->test('or')) { + $this->parser->getStream()->next(); + $right = $this->parseAndExpression(); + $left = new Twig_Node_Expression_Binary_Or($left, $right, $lineno); + $lineno = $this->parser->getCurrentToken()->getLine(); + } - return new Twig_Node_Expression_Compare($expr, $ops, $lineno); - } + return $left; + } - public function parseAddExpression() - { - $lineno = $this->parser->getCurrentToken()->getLine(); - $left = $this->parseSubExpression(); - while ($this->parser->getStream()->test(Twig_Token::OPERATOR_TYPE, '+')) + public function parseAndExpression() { - $this->parser->getStream()->next(); - $right = $this->parseSubExpression(); - $left = new Twig_Node_Expression_Binary_Add($left, $right, $lineno); - $lineno = $this->parser->getCurrentToken()->getLine(); - } + $lineno = $this->parser->getCurrentToken()->getLine(); + $left = $this->parseCompareExpression(); + while ($this->parser->getStream()->test('and')) { + $this->parser->getStream()->next(); + $right = $this->parseCompareExpression(); + $left = new Twig_Node_Expression_Binary_And($left, $right, $lineno); + $lineno = $this->parser->getCurrentToken()->getLine(); + } - return $left; - } + return $left; + } - public function parseSubExpression() - { - $lineno = $this->parser->getCurrentToken()->getLine(); - $left = $this->parseConcatExpression(); - while ($this->parser->getStream()->test(Twig_Token::OPERATOR_TYPE, '-')) + public function parseCompareExpression() { - $this->parser->getStream()->next(); - $right = $this->parseConcatExpression(); - $left = new Twig_Node_Expression_Binary_Sub($left, $right, $lineno); - $lineno = $this->parser->getCurrentToken()->getLine(); - } + static $operators = array('==', '!=', '<', '>', '>=', '<='); + $lineno = $this->parser->getCurrentToken()->getLine(); + $expr = $this->parseAddExpression(); + $ops = array(); + while ( + $this->parser->getStream()->test(Twig_Token::OPERATOR_TYPE, $operators) + || + $this->parser->getStream()->test(Twig_Token::NAME_TYPE, 'in') + ) { + $ops[] = array($this->parser->getStream()->next()->getValue(), $this->parseAddExpression()); + } - return $left; - } + if (empty($ops)) { + return $expr; + } - public function parseConcatExpression() - { - $lineno = $this->parser->getCurrentToken()->getLine(); - $left = $this->parseMulExpression(); - while ($this->parser->getStream()->test(Twig_Token::OPERATOR_TYPE, '~')) - { - $this->parser->getStream()->next(); - $right = $this->parseMulExpression(); - $left = new Twig_Node_Expression_Binary_Concat($left, $right, $lineno); - $lineno = $this->parser->getCurrentToken()->getLine(); + return new Twig_Node_Expression_Compare($expr, $ops, $lineno); } - return $left; - } - - public function parseMulExpression() - { - $lineno = $this->parser->getCurrentToken()->getLine(); - $left = $this->parseDivExpression(); - while ($this->parser->getStream()->test(Twig_Token::OPERATOR_TYPE, '*')) + public function parseAddExpression() { - $this->parser->getStream()->next(); - $right = $this->parseDivExpression(); - $left = new Twig_Node_Expression_Binary_Mul($left, $right, $lineno); - $lineno = $this->parser->getCurrentToken()->getLine(); - } + $lineno = $this->parser->getCurrentToken()->getLine(); + $left = $this->parseSubExpression(); + while ($this->parser->getStream()->test(Twig_Token::OPERATOR_TYPE, '+')) { + $this->parser->getStream()->next(); + $right = $this->parseSubExpression(); + $left = new Twig_Node_Expression_Binary_Add($left, $right, $lineno); + $lineno = $this->parser->getCurrentToken()->getLine(); + } - return $left; - } + return $left; + } - public function parseDivExpression() - { - $lineno = $this->parser->getCurrentToken()->getLine(); - $left = $this->parseFloorDivExpression(); - while ($this->parser->getStream()->test(Twig_Token::OPERATOR_TYPE, '/')) + public function parseSubExpression() { - $this->parser->getStream()->next(); - $right = $this->parseModExpression(); - $left = new Twig_Node_Expression_Binary_Div($left, $right, $lineno); - $lineno = $this->parser->getCurrentToken()->getLine(); - } + $lineno = $this->parser->getCurrentToken()->getLine(); + $left = $this->parseConcatExpression(); + while ($this->parser->getStream()->test(Twig_Token::OPERATOR_TYPE, '-')) { + $this->parser->getStream()->next(); + $right = $this->parseConcatExpression(); + $left = new Twig_Node_Expression_Binary_Sub($left, $right, $lineno); + $lineno = $this->parser->getCurrentToken()->getLine(); + } - return $left; - } + return $left; + } - public function parseFloorDivExpression() - { - $lineno = $this->parser->getCurrentToken()->getLine(); - $left = $this->parseModExpression(); - while ($this->parser->getStream()->test(Twig_Token::OPERATOR_TYPE, '//')) + public function parseConcatExpression() { - $this->parser->getStream()->next(); - $right = $this->parseModExpression(); - $left = new Twig_Node_Expression_Binary_FloorDiv($left, $right, $lineno); - $lineno = $this->parser->getCurrentToken()->getLine(); - } + $lineno = $this->parser->getCurrentToken()->getLine(); + $left = $this->parseMulExpression(); + while ($this->parser->getStream()->test(Twig_Token::OPERATOR_TYPE, '~')) { + $this->parser->getStream()->next(); + $right = $this->parseMulExpression(); + $left = new Twig_Node_Expression_Binary_Concat($left, $right, $lineno); + $lineno = $this->parser->getCurrentToken()->getLine(); + } - return $left; - } + return $left; + } - public function parseModExpression() - { - $lineno = $this->parser->getCurrentToken()->getLine(); - $left = $this->parseUnaryExpression(); - while ($this->parser->getStream()->test(Twig_Token::OPERATOR_TYPE, '%')) + public function parseMulExpression() { - $this->parser->getStream()->next(); - $right = $this->parseUnaryExpression(); - $left = new Twig_Node_Expression_Binary_Mod($left, $right, $lineno); - $lineno = $this->parser->getCurrentToken()->getLine(); - } + $lineno = $this->parser->getCurrentToken()->getLine(); + $left = $this->parseDivExpression(); + while ($this->parser->getStream()->test(Twig_Token::OPERATOR_TYPE, '*')) { + $this->parser->getStream()->next(); + $right = $this->parseDivExpression(); + $left = new Twig_Node_Expression_Binary_Mul($left, $right, $lineno); + $lineno = $this->parser->getCurrentToken()->getLine(); + } - return $left; - } + return $left; + } - public function parseUnaryExpression() - { - if ($this->parser->getStream()->test('not')) + public function parseDivExpression() { - return $this->parseNotExpression(); + $lineno = $this->parser->getCurrentToken()->getLine(); + $left = $this->parseFloorDivExpression(); + while ($this->parser->getStream()->test(Twig_Token::OPERATOR_TYPE, '/')) { + $this->parser->getStream()->next(); + $right = $this->parseModExpression(); + $left = new Twig_Node_Expression_Binary_Div($left, $right, $lineno); + $lineno = $this->parser->getCurrentToken()->getLine(); + } + + return $left; } - if ($this->parser->getCurrentToken()->getType() == Twig_Token::OPERATOR_TYPE) + + public function parseFloorDivExpression() { - switch ($this->parser->getCurrentToken()->getValue()) - { - case '-': - return $this->parseNegExpression(); - case '+': - return $this->parsePosExpression(); - } - } + $lineno = $this->parser->getCurrentToken()->getLine(); + $left = $this->parseModExpression(); + while ($this->parser->getStream()->test(Twig_Token::OPERATOR_TYPE, '//')) { + $this->parser->getStream()->next(); + $right = $this->parseModExpression(); + $left = new Twig_Node_Expression_Binary_FloorDiv($left, $right, $lineno); + $lineno = $this->parser->getCurrentToken()->getLine(); + } - return $this->parsePrimaryExpression(); - } + return $left; + } - public function parseNotExpression() - { - $token = $this->parser->getStream()->next(); - $node = $this->parseUnaryExpression(); + public function parseModExpression() + { + $lineno = $this->parser->getCurrentToken()->getLine(); + $left = $this->parseUnaryExpression(); + while ($this->parser->getStream()->test(Twig_Token::OPERATOR_TYPE, '%')) { + $this->parser->getStream()->next(); + $right = $this->parseUnaryExpression(); + $left = new Twig_Node_Expression_Binary_Mod($left, $right, $lineno); + $lineno = $this->parser->getCurrentToken()->getLine(); + } - return new Twig_Node_Expression_Unary_Not($node, $token->getLine()); - } + return $left; + } - public function parseNegExpression() - { - $token = $this->parser->getStream()->next(); - $node = $this->parseUnaryExpression(); + public function parseUnaryExpression() + { + if ($this->parser->getStream()->test('not')) { + return $this->parseNotExpression(); + } + if ($this->parser->getCurrentToken()->getType() == Twig_Token::OPERATOR_TYPE) { + switch ($this->parser->getCurrentToken()->getValue()) { + case '-': + return $this->parseNegExpression(); + case '+': + return $this->parsePosExpression(); + } + } - return new Twig_Node_Expression_Unary_Neg($node, $token->getLine()); - } + return $this->parsePrimaryExpression(); + } - public function parsePosExpression() - { - $token = $this->parser->getStream()->next(); - $node = $this->parseUnaryExpression(); + public function parseNotExpression() + { + $token = $this->parser->getStream()->next(); + $node = $this->parseUnaryExpression(); - return new Twig_Node_Expression_Unary_Pos($node, $token->getLine()); - } + return new Twig_Node_Expression_Unary_Not($node, $token->getLine()); + } - public function parsePrimaryExpression($assignment = false) - { - $token = $this->parser->getCurrentToken(); - switch ($token->getType()) + public function parseNegExpression() { - case Twig_Token::NAME_TYPE: - $this->parser->getStream()->next(); - switch ($token->getValue()) - { - case 'true': - $node = new Twig_Node_Expression_Constant(true, $token->getLine()); - break; - - case 'false': - $node = new Twig_Node_Expression_Constant(false, $token->getLine()); - break; - - case 'none': - $node = new Twig_Node_Expression_Constant(null, $token->getLine()); - break; - - default: - $cls = $assignment ? 'Twig_Node_Expression_AssignName' : 'Twig_Node_Expression_Name'; - $node = new $cls($token->getValue(), $token->getLine()); - } - break; + $token = $this->parser->getStream()->next(); + $node = $this->parseUnaryExpression(); - case Twig_Token::NUMBER_TYPE: - case Twig_Token::STRING_TYPE: - $this->parser->getStream()->next(); - $node = new Twig_Node_Expression_Constant($token->getValue(), $token->getLine()); - break; - - default: - if ($token->test(Twig_Token::OPERATOR_TYPE, '[')) - { - $this->parser->getStream()->next(); - $node = $this->parseArrayExpression(); - $this->parser->getStream()->expect(Twig_Token::OPERATOR_TYPE, ']'); - } - elseif ($token->test(Twig_Token::OPERATOR_TYPE, '(')) - { - $this->parser->getStream()->next(); - $node = $this->parseExpression(); - $this->parser->getStream()->expect(Twig_Token::OPERATOR_TYPE, ')'); - } - else - { - throw new Twig_SyntaxError(sprintf('Unexpected token "%s"', $token->getValue()), $token->getLine()); - } + return new Twig_Node_Expression_Unary_Neg($node, $token->getLine()); } - if (!$assignment) + + public function parsePosExpression() { - $node = $this->parsePostfixExpression($node); - } + $token = $this->parser->getStream()->next(); + $node = $this->parseUnaryExpression(); - return $node; - } + return new Twig_Node_Expression_Unary_Pos($node, $token->getLine()); + } - public function parseArrayExpression() - { - $elements = array(); - while (!$this->parser->getStream()->test(Twig_Token::OPERATOR_TYPE, ']')) + public function parsePrimaryExpression($assignment = false) { - if (!empty($elements)) - { - $this->parser->getStream()->expect(Twig_Token::OPERATOR_TYPE, ','); - - // trailing ,? - if ($this->parser->getStream()->test(Twig_Token::OPERATOR_TYPE, ']')) - { - return new Twig_Node_Expression_Array($elements, $this->parser->getCurrentToken()->getLine()); + $token = $this->parser->getCurrentToken(); + switch ($token->getType()) { + case Twig_Token::NAME_TYPE: + $this->parser->getStream()->next(); + switch ($token->getValue()) { + case 'true': + $node = new Twig_Node_Expression_Constant(true, $token->getLine()); + break; + + case 'false': + $node = new Twig_Node_Expression_Constant(false, $token->getLine()); + break; + + case 'none': + $node = new Twig_Node_Expression_Constant(null, $token->getLine()); + break; + + default: + $cls = $assignment ? 'Twig_Node_Expression_AssignName' : 'Twig_Node_Expression_Name'; + $node = new $cls($token->getValue(), $token->getLine()); + } + break; + + case Twig_Token::NUMBER_TYPE: + case Twig_Token::STRING_TYPE: + $this->parser->getStream()->next(); + $node = new Twig_Node_Expression_Constant($token->getValue(), $token->getLine()); + break; + + default: + if ($token->test(Twig_Token::OPERATOR_TYPE, '[')) { + $this->parser->getStream()->next(); + $node = $this->parseArrayExpression(); + $this->parser->getStream()->expect(Twig_Token::OPERATOR_TYPE, ']'); + } elseif ($token->test(Twig_Token::OPERATOR_TYPE, '(')) { + $this->parser->getStream()->next(); + $node = $this->parseExpression(); + $this->parser->getStream()->expect(Twig_Token::OPERATOR_TYPE, ')'); + } else { + throw new Twig_SyntaxError(sprintf('Unexpected token "%s"', $token->getValue()), $token->getLine()); + } } - } - - // hash or array element? - if ( - $this->parser->getStream()->test(Twig_Token::STRING_TYPE) - || - $this->parser->getStream()->test(Twig_Token::NUMBER_TYPE) - ) - { - if ($this->parser->getStream()->look()->test(Twig_Token::OPERATOR_TYPE, ':')) - { - // hash - $key = $this->parser->getStream()->next()->getValue(); - $this->parser->getStream()->next(); - - $elements[$key] = $this->parseExpression(); - - continue; + if (!$assignment) { + $node = $this->parsePostfixExpression($node); } - $this->parser->getStream()->rewind(); - } - $elements[] = $this->parseExpression(); + return $node; } - return new Twig_Node_Expression_Array($elements, $this->parser->getCurrentToken()->getLine()); - } - - public function parsePostfixExpression($node) - { - $stop = false; - while (!$stop && $this->parser->getCurrentToken()->getType() == Twig_Token::OPERATOR_TYPE) + public function parseArrayExpression() { - switch ($this->parser->getCurrentToken()->getValue()) - { - case '..': - $node = $this->parseRangeExpression($node); - break; - - case '.': - case '[': - $node = $this->parseSubscriptExpression($node); - break; - - case '|': - $node = $this->parseFilterExpression($node); - break; - - default: - $stop = true; - break; - } + $elements = array(); + while (!$this->parser->getStream()->test(Twig_Token::OPERATOR_TYPE, ']')) { + if (!empty($elements)) { + $this->parser->getStream()->expect(Twig_Token::OPERATOR_TYPE, ','); + + // trailing ,? + if ($this->parser->getStream()->test(Twig_Token::OPERATOR_TYPE, ']')) { + return new Twig_Node_Expression_Array($elements, $this->parser->getCurrentToken()->getLine()); + } + } + + // hash or array element? + if ( + $this->parser->getStream()->test(Twig_Token::STRING_TYPE) + || + $this->parser->getStream()->test(Twig_Token::NUMBER_TYPE) + ) + { + if ($this->parser->getStream()->look()->test(Twig_Token::OPERATOR_TYPE, ':')) { + // hash + $key = $this->parser->getStream()->next()->getValue(); + $this->parser->getStream()->next(); + + $elements[$key] = $this->parseExpression(); + + continue; + } + $this->parser->getStream()->rewind(); + } + + $elements[] = $this->parseExpression(); + } + + return new Twig_Node_Expression_Array($elements, $this->parser->getCurrentToken()->getLine()); } - return $node; - } + public function parsePostfixExpression($node) + { + $stop = false; + while (!$stop && $this->parser->getCurrentToken()->getType() == Twig_Token::OPERATOR_TYPE) { + switch ($this->parser->getCurrentToken()->getValue()) { + case '..': + $node = $this->parseRangeExpression($node); + break; + + case '.': + case '[': + $node = $this->parseSubscriptExpression($node); + break; + + case '|': + $node = $this->parseFilterExpression($node); + break; + + default: + $stop = true; + break; + } + } - public function parseRangeExpression($node) - { - $token = $this->parser->getStream()->next(); - $lineno = $token->getLine(); + return $node; + } - $end = $this->parseExpression(); + public function parseRangeExpression($node) + { + $token = $this->parser->getStream()->next(); + $lineno = $token->getLine(); - return new Twig_Node_Expression_Filter($node, array(array('range', array($end))), $lineno); - } + $end = $this->parseExpression(); - public function parseSubscriptExpression($node) - { - $token = $this->parser->getStream()->next(); - $lineno = $token->getLine(); - $arguments = array(); - if ($token->getValue() == '.') - { - $token = $this->parser->getStream()->next(); - if ($token->getType() == Twig_Token::NAME_TYPE || $token->getType() == Twig_Token::NUMBER_TYPE) - { - $arg = new Twig_Node_Expression_Constant($token->getValue(), $lineno); - - $arguments = $this->parseArguments(); - } - else - { - throw new Twig_SyntaxError('Expected name or number', $lineno); - } + return new Twig_Node_Expression_Filter($node, array(array('range', array($end))), $lineno); } - else + + public function parseSubscriptExpression($node) { - $arg = $this->parseExpression(); - $this->parser->getStream()->expect(Twig_Token::OPERATOR_TYPE, ']'); - } + $token = $this->parser->getStream()->next(); + $lineno = $token->getLine(); + $arguments = array(); + if ($token->getValue() == '.') { + $token = $this->parser->getStream()->next(); + if ($token->getType() == Twig_Token::NAME_TYPE || $token->getType() == Twig_Token::NUMBER_TYPE) { + $arg = new Twig_Node_Expression_Constant($token->getValue(), $lineno); + + $arguments = $this->parseArguments(); + } else { + throw new Twig_SyntaxError('Expected name or number', $lineno); + } + } else { + $arg = $this->parseExpression(); + $this->parser->getStream()->expect(Twig_Token::OPERATOR_TYPE, ']'); + } - return new Twig_Node_Expression_GetAttr($node, $arg, $arguments, $lineno, $token->getValue()); - } + return new Twig_Node_Expression_GetAttr($node, $arg, $arguments, $lineno, $token->getValue()); + } - public function parseFilterExpression($node) - { - $lineno = $this->parser->getCurrentToken()->getLine(); + public function parseFilterExpression($node) + { + $lineno = $this->parser->getCurrentToken()->getLine(); - $this->parser->getStream()->next(); + $this->parser->getStream()->next(); - return new Twig_Node_Expression_Filter($node, $this->parseFilterExpressionRaw(), $lineno); - } + return new Twig_Node_Expression_Filter($node, $this->parseFilterExpressionRaw(), $lineno); + } - public function parseFilterExpressionRaw() - { - $filters = array(); - while (true) + public function parseFilterExpressionRaw() { - $token = $this->parser->getStream()->expect(Twig_Token::NAME_TYPE); - - $filters[] = array($token->getValue(), $this->parseArguments()); + $filters = array(); + while (true) { + $token = $this->parser->getStream()->expect(Twig_Token::NAME_TYPE); - if (!$this->parser->getStream()->test(Twig_Token::OPERATOR_TYPE, '|')) - { - break; - } + $filters[] = array($token->getValue(), $this->parseArguments()); - $this->parser->getStream()->next(); - } + if (!$this->parser->getStream()->test(Twig_Token::OPERATOR_TYPE, '|')) { + break; + } - return $filters; - } + $this->parser->getStream()->next(); + } - public function parseArguments() - { - if (!$this->parser->getStream()->test(Twig_Token::OPERATOR_TYPE, '(')) - { - return array(); + return $filters; } - $args = array(); - $this->parser->getStream()->next(); - while (!$this->parser->getStream()->test(Twig_Token::OPERATOR_TYPE, ')')) + public function parseArguments() { - if (!empty($args)) - { - $this->parser->getStream()->expect(Twig_Token::OPERATOR_TYPE, ','); - } - $args[] = $this->parseExpression(); - } - $this->parser->getStream()->expect(Twig_Token::OPERATOR_TYPE, ')'); + if (!$this->parser->getStream()->test(Twig_Token::OPERATOR_TYPE, '(')) { + return array(); + } - return $args; - } + $args = array(); + $this->parser->getStream()->next(); + while (!$this->parser->getStream()->test(Twig_Token::OPERATOR_TYPE, ')')) { + if (!empty($args)) { + $this->parser->getStream()->expect(Twig_Token::OPERATOR_TYPE, ','); + } + $args[] = $this->parseExpression(); + } + $this->parser->getStream()->expect(Twig_Token::OPERATOR_TYPE, ')'); - public function parseAssignmentExpression() - { - $lineno = $this->parser->getCurrentToken()->getLine(); - $targets = array(); - $is_multitarget = false; - while (true) - { - if (!empty($targets)) - { - $this->parser->getStream()->expect(Twig_Token::OPERATOR_TYPE, ','); - } - if ($this->parser->getStream()->test(Twig_Token::OPERATOR_TYPE, ')') || - $this->parser->getStream()->test(Twig_Token::VAR_END_TYPE) || - $this->parser->getStream()->test(Twig_Token::BLOCK_END_TYPE) || - $this->parser->getStream()->test('in')) - { - break; - } - $targets[] = $this->parsePrimaryExpression(true); - if (!$this->parser->getStream()->test(Twig_Token::OPERATOR_TYPE, ',')) - { - break; - } - $is_multitarget = true; + return $args; } - if (!$is_multitarget && count($targets) == 1) - { - return array(false, $targets[0]); - } - - return array(true, $targets); - } - public function parseMultitargetExpression() - { - $lineno = $this->parser->getCurrentToken()->getLine(); - $targets = array(); - $is_multitarget = false; - while (true) + public function parseAssignmentExpression() { - if (!empty($targets)) - { - $this->parser->getStream()->expect(Twig_Token::OPERATOR_TYPE, ','); - } - if ($this->parser->getStream()->test(Twig_Token::OPERATOR_TYPE, ')') || - $this->parser->getStream()->test(Twig_Token::VAR_END_TYPE) || - $this->parser->getStream()->test(Twig_Token::BLOCK_END_TYPE)) - { - break; - } - $targets[] = $this->parseExpression(); - if (!$this->parser->getStream()->test(Twig_Token::OPERATOR_TYPE, ',')) - { - break; - } - $is_multitarget = true; + $lineno = $this->parser->getCurrentToken()->getLine(); + $targets = array(); + $is_multitarget = false; + while (true) { + if (!empty($targets)) { + $this->parser->getStream()->expect(Twig_Token::OPERATOR_TYPE, ','); + } + if ($this->parser->getStream()->test(Twig_Token::OPERATOR_TYPE, ')') || + $this->parser->getStream()->test(Twig_Token::VAR_END_TYPE) || + $this->parser->getStream()->test(Twig_Token::BLOCK_END_TYPE) || + $this->parser->getStream()->test('in')) + { + break; + } + $targets[] = $this->parsePrimaryExpression(true); + if (!$this->parser->getStream()->test(Twig_Token::OPERATOR_TYPE, ',')) { + break; + } + $is_multitarget = true; + } + if (!$is_multitarget && count($targets) == 1) { + return array(false, $targets[0]); + } + + return array(true, $targets); } - if (!$is_multitarget && count($targets) == 1) + + public function parseMultitargetExpression() { - return array(false, $targets[0]); - } + $lineno = $this->parser->getCurrentToken()->getLine(); + $targets = array(); + $is_multitarget = false; + while (true) { + if (!empty($targets)) { + $this->parser->getStream()->expect(Twig_Token::OPERATOR_TYPE, ','); + } + if ($this->parser->getStream()->test(Twig_Token::OPERATOR_TYPE, ')') || + $this->parser->getStream()->test(Twig_Token::VAR_END_TYPE) || + $this->parser->getStream()->test(Twig_Token::BLOCK_END_TYPE)) + { + break; + } + $targets[] = $this->parseExpression(); + if (!$this->parser->getStream()->test(Twig_Token::OPERATOR_TYPE, ',')) { + break; + } + $is_multitarget = true; + } + if (!$is_multitarget && count($targets) == 1) { + return array(false, $targets[0]); + } - return array(true, $targets); - } + return array(true, $targets); + } } diff --git a/lib/Twig/Extension.php b/lib/Twig/Extension.php index a3c8156..00bc6d7 100644 --- a/lib/Twig/Extension.php +++ b/lib/Twig/Extension.php @@ -10,42 +10,42 @@ */ 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. - */ - public function initRuntime() - { - } + /** + * Initializes the runtime environment. + * + * This is where you can load some file that contains filter functions for instance. + */ + public function initRuntime() + { + } - /** - * Returns the token parser instances to add to the existing list. - * - * @return array An array of Twig_TokenParser instances - */ - public function getTokenParsers() - { - return array(); - } + /** + * Returns the token parser instances to add to the existing list. + * + * @return array An array of Twig_TokenParser 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 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 filters to add to the existing list. + * + * @return array An array of filters + */ + public function getFilters() + { + return array(); + } } diff --git a/lib/Twig/Extension/Core.php b/lib/Twig/Extension/Core.php index 3e9f908..04bba6f 100644 --- a/lib/Twig/Extension/Core.php +++ b/lib/Twig/Extension/Core.php @@ -10,207 +10,195 @@ */ class Twig_Extension_Core extends Twig_Extension { - /** - * Returns the token parser instance to add to the existing list. - * - * @return array An array of Twig_TokenParser instances - */ - public function getTokenParsers() - { - return array( - new Twig_TokenParser_For(), - new Twig_TokenParser_If(), - new Twig_TokenParser_Extends(), - new Twig_TokenParser_Include(), - new Twig_TokenParser_Block(), - new Twig_TokenParser_Parent(), - new Twig_TokenParser_Display(), - new Twig_TokenParser_Filter(), - new Twig_TokenParser_Macro(), - new Twig_TokenParser_Import(), - new Twig_TokenParser_Set(), - new Twig_TokenParser_Debug(), - ); - } - - /** - * 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_Filter()); - } - - /** - * Returns a list of filters to add to the existing list. - * - * @return array An array of filters - */ - public function getFilters() - { - $filters = array( - // formatting filters - 'date' => new Twig_Filter_Function('twig_date_format_filter'), - 'format' => new Twig_Filter_Function('sprintf'), - - // numbers - 'even' => new Twig_Filter_Function('twig_is_even_filter'), - 'odd' => new Twig_Filter_Function('twig_is_odd_filter'), - - // encoding - 'urlencode' => new Twig_Filter_Function('twig_urlencode_filter', array('is_escaper' => true)), - - // string filters - 'title' => new Twig_Filter_Function('twig_title_string_filter', array('needs_environment' => true)), - 'capitalize' => new Twig_Filter_Function('twig_capitalize_string_filter', array('needs_environment' => true)), - 'upper' => new Twig_Filter_Function('strtoupper'), - 'lower' => new Twig_Filter_Function('strtolower'), - 'striptags' => new Twig_Filter_Function('strip_tags'), - - // array helpers - 'join' => new Twig_Filter_Function('twig_join_filter'), - 'reverse' => new Twig_Filter_Function('twig_reverse_filter'), - 'length' => new Twig_Filter_Function('twig_length_filter', array('needs_environment' => true)), - 'sort' => new Twig_Filter_Function('twig_sort_filter'), - 'in' => new Twig_Filter_Function('twig_in_filter'), - 'range' => new Twig_Filter_Function('twig_range_filter'), - 'cycle' => new Twig_Filter_Function('twig_cycle_filter'), - - // iteration and runtime - 'default' => new Twig_Filter_Function('twig_default_filter'), - 'keys' => new Twig_Filter_Function('twig_get_array_keys_filter'), - 'items' => new Twig_Filter_Function('twig_get_array_items_filter'), - - // escaping - 'escape' => new Twig_Filter_Function('twig_escape_filter', array('needs_environment' => true, 'is_escaper' => true)), - 'e' => new Twig_Filter_Function('twig_escape_filter', array('needs_environment' => true, 'is_escaper' => true)), - ); - - if (function_exists('mb_get_info')) + /** + * Returns the token parser instance to add to the existing list. + * + * @return array An array of Twig_TokenParser instances + */ + public function getTokenParsers() { - $filters['upper'] = new Twig_Filter_Function('twig_upper_filter', array('needs_environment' => true)); - $filters['lower'] = new Twig_Filter_Function('twig_lower_filter', array('needs_environment' => true)); + return array( + new Twig_TokenParser_For(), + new Twig_TokenParser_If(), + new Twig_TokenParser_Extends(), + new Twig_TokenParser_Include(), + new Twig_TokenParser_Block(), + new Twig_TokenParser_Parent(), + new Twig_TokenParser_Display(), + new Twig_TokenParser_Filter(), + new Twig_TokenParser_Macro(), + new Twig_TokenParser_Import(), + new Twig_TokenParser_Set(), + new Twig_TokenParser_Debug(), + ); } - return $filters; - } - - /** - * Returns the name of the extension. - * - * @return string The extension name - */ - public function getName() - { - return 'core'; - } + /** + * 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_Filter()); + } + + /** + * Returns a list of filters to add to the existing list. + * + * @return array An array of filters + */ + public function getFilters() + { + $filters = array( + // formatting filters + 'date' => new Twig_Filter_Function('twig_date_format_filter'), + 'format' => new Twig_Filter_Function('sprintf'), + + // numbers + 'even' => new Twig_Filter_Function('twig_is_even_filter'), + 'odd' => new Twig_Filter_Function('twig_is_odd_filter'), + + // encoding + 'urlencode' => new Twig_Filter_Function('twig_urlencode_filter', array('is_escaper' => true)), + + // string filters + 'title' => new Twig_Filter_Function('twig_title_string_filter', array('needs_environment' => true)), + 'capitalize' => new Twig_Filter_Function('twig_capitalize_string_filter', array('needs_environment' => true)), + 'upper' => new Twig_Filter_Function('strtoupper'), + 'lower' => new Twig_Filter_Function('strtolower'), + 'striptags' => new Twig_Filter_Function('strip_tags'), + + // array helpers + 'join' => new Twig_Filter_Function('twig_join_filter'), + 'reverse' => new Twig_Filter_Function('twig_reverse_filter'), + 'length' => new Twig_Filter_Function('twig_length_filter', array('needs_environment' => true)), + 'sort' => new Twig_Filter_Function('twig_sort_filter'), + 'in' => new Twig_Filter_Function('twig_in_filter'), + 'range' => new Twig_Filter_Function('twig_range_filter'), + 'cycle' => new Twig_Filter_Function('twig_cycle_filter'), + + // iteration and runtime + 'default' => new Twig_Filter_Function('twig_default_filter'), + 'keys' => new Twig_Filter_Function('twig_get_array_keys_filter'), + 'items' => new Twig_Filter_Function('twig_get_array_items_filter'), + + // escaping + 'escape' => new Twig_Filter_Function('twig_escape_filter', array('needs_environment' => true, 'is_escaper' => true)), + 'e' => new Twig_Filter_Function('twig_escape_filter', array('needs_environment' => true, 'is_escaper' => true)), + ); + + if (function_exists('mb_get_info')) { + $filters['upper'] = new Twig_Filter_Function('twig_upper_filter', array('needs_environment' => true)); + $filters['lower'] = new Twig_Filter_Function('twig_lower_filter', array('needs_environment' => true)); + } + + return $filters; + } + + /** + * Returns the name of the extension. + * + * @return string The extension name + */ + public function getName() + { + return 'core'; + } } function twig_date_format_filter($timestamp, $format = 'F j, Y H:i') { - return $timestamp instanceof DateTime ? $timestamp->format($format) : date($format, $timestamp); + return $timestamp instanceof DateTime ? $timestamp->format($format) : date($format, $timestamp); } function twig_urlencode_filter($url, $raw = false) { - if ($raw) - { - return rawurlencode($url); - } + if ($raw) { + return rawurlencode($url); + } - return urlencode($url); + return urlencode($url); } function twig_join_filter($value, $glue = '') { - return implode($glue, (array) $value); + return implode($glue, (array) $value); } function twig_default_filter($value, $default = '') { - return is_null($value) ? $default : $value; + return is_null($value) ? $default : $value; } function twig_get_array_keys_filter($array) { - if (is_object($array) && $array instanceof Traversable) - { - return array_keys(iterator_to_array($array)); - } + if (is_object($array) && $array instanceof Traversable) { + return array_keys(iterator_to_array($array)); + } - if (!is_array($array)) - { - return array(); - } + if (!is_array($array)) { + return array(); + } - return array_keys($array); + return array_keys($array); } function twig_reverse_filter($array) { - if (is_object($array) && $array instanceof Traversable) - { - return array_reverse(iterator_to_array($array)); - } + if (is_object($array) && $array instanceof Traversable) { + return array_reverse(iterator_to_array($array)); + } - if (!is_array($array)) - { - return array(); - } + if (!is_array($array)) { + return array(); + } - return array_reverse($array); + return array_reverse($array); } function twig_is_even_filter($value) { - return $value % 2 == 0; + return $value % 2 == 0; } function twig_is_odd_filter($value) { - return $value % 2 == 1; + return $value % 2 == 1; } function twig_sort_filter($array) { - asort($array); + asort($array); - return $array; + return $array; } function twig_in_filter($value, $compare) { - if (is_array($compare)) - { - return in_array($value, $compare); - } - elseif (is_string($compare)) - { - return false !== strpos($compare, (string) $value); - } - elseif (is_object($compare) && $compare instanceof Traversable) - { - return in_array($value, iterator_to_array($compare)); - } - - return false; + if (is_array($compare)) { + return in_array($value, $compare); + } elseif (is_string($compare)) { + return false !== strpos($compare, (string) $value); + } elseif (is_object($compare) && $compare instanceof Traversable) { + return in_array($value, iterator_to_array($compare)); + } + + return false; } function twig_range_filter($start, $end, $step = 1) { - return range($start, $end, $step); + return range($start, $end, $step); } function twig_cycle_filter($values, $i) { - if (!is_array($values) && !$values instanceof ArrayAccess) - { - return $values; - } + if (!is_array($values) && !$values instanceof ArrayAccess) { + return $values; + } - return $values[$i % count($values)]; + return $values[$i % count($values)]; } /* @@ -227,111 +215,99 @@ function twig_cycle_filter($values, $i) */ function twig_escape_filter(Twig_Environment $env, $string, $type = 'html') { - if (!is_string($string)) - { - return $string; - } - - switch ($type) - { - case 'js': - // a function the c-escapes a string, making it suitable to be placed in a JavaScript string - return str_replace(array("\\" , "\n" , "\r" , "\"" , "'"), - array("\\\\", "\\n" , "\\r", "\\\"", "\\'"), - $string); - case 'html': - default: - return htmlspecialchars($string, ENT_QUOTES, $env->getCharset()); - } + if (!is_string($string)) { + return $string; + } + + switch ($type) { + case 'js': + // a function the c-escapes a string, making it suitable to be placed in a JavaScript string + return str_replace(array("\\" , "\n" , "\r" , "\"" , "'"), + array("\\\\", "\\n" , "\\r", "\\\"", "\\'"), + $string); + case 'html': + default: + return htmlspecialchars($string, ENT_QUOTES, $env->getCharset()); + } } // add multibyte extensions if possible -if (function_exists('mb_get_info')) -{ - function twig_length_filter(Twig_Environment $env, $thing) - { - return is_string($thing) ? mb_strlen($thing, $env->getCharset()) : count($thing); - } - - function twig_upper_filter(Twig_Environment $env, $string) - { - if (!is_null($env->getCharset())) +if (function_exists('mb_get_info')) { + function twig_length_filter(Twig_Environment $env, $thing) { - return mb_strtoupper($string, $env->getCharset()); + return is_string($thing) ? mb_strlen($thing, $env->getCharset()) : count($thing); } - return strtoupper($string); - } - - function twig_lower_filter(Twig_Environment $env, $string) - { - if (!is_null($env->getCharset())) + function twig_upper_filter(Twig_Environment $env, $string) { - return mb_strtolower($string, $env->getCharset()); - } + if (!is_null($env->getCharset())) { + return mb_strtoupper($string, $env->getCharset()); + } - return strtolower($string); - } + return strtoupper($string); + } - function twig_title_string_filter(Twig_Environment $env, $string) - { - if (is_null($env->getCharset())) + function twig_lower_filter(Twig_Environment $env, $string) { - return ucwords(strtolower($string)); - } + if (!is_null($env->getCharset())) { + return mb_strtolower($string, $env->getCharset()); + } - return mb_convert_case($string, MB_CASE_TITLE, $env->getCharset()); - } + return strtolower($string); + } - function twig_capitalize_string_filter(Twig_Environment $env, $string) - { - if (is_null($env->getCharset())) + function twig_title_string_filter(Twig_Environment $env, $string) { - return ucfirst(strtolower($string)); + if (is_null($env->getCharset())) { + return ucwords(strtolower($string)); + } + + return mb_convert_case($string, MB_CASE_TITLE, $env->getCharset()); } - return mb_strtoupper(mb_substr($string, 0, 1, $env->getCharset())). - mb_strtolower(mb_substr($string, 1, mb_strlen($string), $env->getCharset()), $env->getCharset()); - } + function twig_capitalize_string_filter(Twig_Environment $env, $string) + { + if (is_null($env->getCharset())) { + return ucfirst(strtolower($string)); + } + + return mb_strtoupper(mb_substr($string, 0, 1, $env->getCharset())). + mb_strtolower(mb_substr($string, 1, mb_strlen($string), $env->getCharset()), $env->getCharset()); + } } // and byte fallback else { - function twig_length_filter(Twig_Environment $env, $thing) - { - return is_string($thing) ? strlen($thing) : count($thing); - } - - function twig_title_string_filter(Twig_Environment $env, $string) - { - return ucwords(strtolower($string)); - } - - function twig_capitalize_string_filter(Twig_Environment $env, $string) - { - return ucfirst(strtolower($string)); - } + function twig_length_filter(Twig_Environment $env, $thing) + { + return is_string($thing) ? strlen($thing) : count($thing); + } + + function twig_title_string_filter(Twig_Environment $env, $string) + { + return ucwords(strtolower($string)); + } + + function twig_capitalize_string_filter(Twig_Environment $env, $string) + { + return ucfirst(strtolower($string)); + } } function twig_iterator_to_array($seq) { - if (is_array($seq)) - { - return $seq; - } - elseif (is_object($seq) && $seq instanceof Traversable) - { - return $seq instanceof Countable ? $seq : iterator_to_array($seq); - } - else - { - return array(); - } + if (is_array($seq)) { + return $seq; + } elseif (is_object($seq) && $seq instanceof Traversable) { + return $seq instanceof Countable ? $seq : iterator_to_array($seq); + } else { + return array(); + } } // only for backward compatibility function twig_get_array_items_filter($array) { - // noop - return $array; + // noop + return $array; } diff --git a/lib/Twig/Extension/Escaper.php b/lib/Twig/Extension/Escaper.php index 4de858e..639f8c6 100644 --- a/lib/Twig/Extension/Escaper.php +++ b/lib/Twig/Extension/Escaper.php @@ -10,63 +10,63 @@ */ class Twig_Extension_Escaper extends Twig_Extension { - protected $autoescape; + protected $autoescape; - public function __construct($autoescape = true) - { - $this->autoescape = $autoescape; - } + public function __construct($autoescape = true) + { + $this->autoescape = $autoescape; + } - /** - * Returns the token parser instance to add to the existing list. - * - * @return array An array of Twig_TokenParser instances - */ - public function getTokenParsers() - { - return array(new Twig_TokenParser_AutoEscape()); - } + /** + * Returns the token parser instance to add to the existing list. + * + * @return array An array of Twig_TokenParser 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 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( - 'safe' => new Twig_Filter_Function('twig_safe_filter', array('is_escaper' => true)), - ); - } + /** + * Returns a list of filters to add to the existing list. + * + * @return array An array of filters + */ + public function getFilters() + { + return array( + 'safe' => new Twig_Filter_Function('twig_safe_filter', array('is_escaper' => true)), + ); + } - public function isGlobal() - { - return $this->autoescape; - } + public function isGlobal() + { + return $this->autoescape; + } - /** - * Returns the name of the extension. - * - * @return string The extension name - */ - public function getName() - { - return 'escaper'; - } + /** + * Returns the name of the extension. + * + * @return string The extension name + */ + public function getName() + { + return 'escaper'; + } } // tells the escaper node visitor that the string is safe function twig_safe_filter($string) { - return $string; + return $string; } diff --git a/lib/Twig/Extension/I18n.php b/lib/Twig/Extension/I18n.php index 88b118c..0e22c24 100644 --- a/lib/Twig/Extension/I18n.php +++ b/lib/Twig/Extension/I18n.php @@ -10,23 +10,23 @@ */ class Twig_Extension_I18n extends Twig_Extension { - /** - * Returns the token parser instance to add to the existing list. - * - * @return array An array of Twig_TokenParser instances - */ - public function getTokenParsers() - { - return array(new Twig_TokenParser_Trans()); - } + /** + * Returns the token parser instance to add to the existing list. + * + * @return array An array of Twig_TokenParser instances + */ + public function getTokenParsers() + { + return array(new Twig_TokenParser_Trans()); + } - /** - * Returns the name of the extension. - * - * @return string The extension name - */ - public function getName() - { - return 'i18n'; - } + /** + * Returns the name of the extension. + * + * @return string The extension name + */ + public function getName() + { + return 'i18n'; + } } diff --git a/lib/Twig/Extension/Sandbox.php b/lib/Twig/Extension/Sandbox.php index ddca886..c45d9b8 100644 --- a/lib/Twig/Extension/Sandbox.php +++ b/lib/Twig/Extension/Sandbox.php @@ -10,87 +10,84 @@ */ class Twig_Extension_Sandbox extends Twig_Extension { - protected $sandboxedGlobally; - protected $sandboxed; - protected $policy; + protected $sandboxedGlobally; + protected $sandboxed; + protected $policy; - public function __construct(Twig_Sandbox_SecurityPolicyInterface $policy, $sandboxed = false) - { - $this->policy = $policy; - $this->sandboxedGlobally = $sandboxed; - } + public function __construct(Twig_Sandbox_SecurityPolicyInterface $policy, $sandboxed = false) + { + $this->policy = $policy; + $this->sandboxedGlobally = $sandboxed; + } - /** - * 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()); - } + /** + * 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()); + } - public function enableSandbox() - { - $this->sandboxed = true; - } + public function enableSandbox() + { + $this->sandboxed = true; + } - public function disableSandbox() - { - $this->sandboxed = false; - } + public function disableSandbox() + { + $this->sandboxed = false; + } - public function isSandboxed() - { - return $this->sandboxedGlobally || $this->sandboxed; - } + public function isSandboxed() + { + return $this->sandboxedGlobally || $this->sandboxed; + } - public function isSandboxedGlobally() - { - return $this->sandboxedGlobally; - } + public function isSandboxedGlobally() + { + return $this->sandboxedGlobally; + } - public function setSecurityPolicy(Twig_Sandbox_SecurityPolicyInterface $policy) - { - $this->policy = $policy; - } + public function setSecurityPolicy(Twig_Sandbox_SecurityPolicyInterface $policy) + { + $this->policy = $policy; + } - public function getSecurityPolicy() - { - return $this->policy; - } + public function getSecurityPolicy() + { + return $this->policy; + } - public function checkSecurity($tags, $filters) - { - if ($this->isSandboxed()) + public function checkSecurity($tags, $filters) { - $this->policy->checkSecurity($tags, $filters); + if ($this->isSandboxed()) { + $this->policy->checkSecurity($tags, $filters); + } } - } - public function checkMethodAllowed($obj, $method) - { - if ($this->isSandboxed()) + public function checkMethodAllowed($obj, $method) { - $this->policy->checkMethodAllowed($obj, $method); + if ($this->isSandboxed()) { + $this->policy->checkMethodAllowed($obj, $method); + } } - } - public function checkPropertyAllowed($obj, $method) - { - if ($this->isSandboxed()) + public function checkPropertyAllowed($obj, $method) { - $this->policy->checkPropertyAllowed($obj, $method); + if ($this->isSandboxed()) { + $this->policy->checkPropertyAllowed($obj, $method); + } } - } - /** - * Returns the name of the extension. - * - * @return string The extension name - */ - public function getName() - { - return 'sandbox'; - } + /** + * Returns the name of the extension. + * + * @return string The extension name + */ + public function getName() + { + return 'sandbox'; + } } diff --git a/lib/Twig/ExtensionInterface.php b/lib/Twig/ExtensionInterface.php index d18c3c3..d0a7add 100644 --- a/lib/Twig/ExtensionInterface.php +++ b/lib/Twig/ExtensionInterface.php @@ -18,38 +18,38 @@ */ interface Twig_ExtensionInterface { - /** - * Initializes the runtime environment. - * - * This is where you can load some file that contains filter functions for instance. - */ - public function initRuntime(); + /** + * Initializes the runtime environment. + * + * This is where you can load some file that contains filter functions for instance. + */ + public function initRuntime(); - /** - * Returns the token parser instances to add to the existing list. - * - * @return array An array of Twig_TokenParser instances - */ - public function getTokenParsers(); + /** + * Returns the token parser instances to add to the existing list. + * + * @return array An array of Twig_TokenParser instances + */ + public function getTokenParsers(); - /** - * Returns the node visitor instances to add to the existing list. - * - * @return array An array of Twig_NodeVisitorInterface instances - */ - public function getNodeVisitors(); + /** + * Returns the node visitor instances to add to the existing list. + * + * @return array An array of Twig_NodeVisitorInterface instances + */ + public function getNodeVisitors(); - /** - * Returns a list of filters to add to the existing list. - * - * @return array An array of filters - */ - public function getFilters(); + /** + * Returns a list of filters to add to the existing list. + * + * @return array An array of filters + */ + public function getFilters(); - /** - * Returns the name of the extension. - * - * @return string The extension name - */ - public function getName(); + /** + * Returns the name of the extension. + * + * @return string The extension name + */ + public function getName(); } diff --git a/lib/Twig/Filter.php b/lib/Twig/Filter.php index 698e01e..8ee4d50 100644 --- a/lib/Twig/Filter.php +++ b/lib/Twig/Filter.php @@ -18,25 +18,25 @@ */ abstract class Twig_Filter { - protected $options; + protected $options; - public function __construct(array $options = array()) - { - $this->options = array_merge(array( - 'needs_environment' => false, - 'is_escaper' => false, - ), $options); - } + public function __construct(array $options = array()) + { + $this->options = array_merge(array( + 'needs_environment' => false, + 'is_escaper' => false, + ), $options); + } - abstract public function compile(); + abstract public function compile(); - public function needsEnvironment() - { - return $this->options['needs_environment']; - } + public function needsEnvironment() + { + return $this->options['needs_environment']; + } - public function isEscaper() - { - return $this->options['is_escaper']; - } + public function isEscaper() + { + return $this->options['is_escaper']; + } } diff --git a/lib/Twig/Filter/Function.php b/lib/Twig/Filter/Function.php index da8e886..2f08288 100644 --- a/lib/Twig/Filter/Function.php +++ b/lib/Twig/Filter/Function.php @@ -18,17 +18,17 @@ */ class Twig_Filter_Function extends Twig_Filter { - protected $function; + protected $function; - public function __construct($function, array $options = array()) - { - parent::__construct($options); + public function __construct($function, array $options = array()) + { + parent::__construct($options); - $this->function = $function; - } + $this->function = $function; + } - public function compile() - { - return $this->function; - } + public function compile() + { + return $this->function; + } } diff --git a/lib/Twig/Filter/Method.php b/lib/Twig/Filter/Method.php index 755eac1..824efe2 100644 --- a/lib/Twig/Filter/Method.php +++ b/lib/Twig/Filter/Method.php @@ -18,18 +18,18 @@ */ class Twig_Filter_Method extends Twig_Filter { - protected $extension, $method; + protected $extension, $method; - public function __construct(Twig_ExtensionInterface $extension, $method, array $options = array()) - { - parent::__construct($options); + public function __construct(Twig_ExtensionInterface $extension, $method, array $options = array()) + { + parent::__construct($options); - $this->extension = $extension; - $this->method = $method; - } + $this->extension = $extension; + $this->method = $method; + } - public function compile() - { - return sprintf('$this->getEnvironment()->getExtension(\'%s\')->%s', $this->extension->getName(), $this->method); - } + public function compile() + { + return sprintf('$this->getEnvironment()->getExtension(\'%s\')->%s', $this->extension->getName(), $this->method); + } } diff --git a/lib/Twig/Lexer.php b/lib/Twig/Lexer.php index 3fa314f..ce3dfcf 100644 --- a/lib/Twig/Lexer.php +++ b/lib/Twig/Lexer.php @@ -19,327 +19,298 @@ */ class Twig_Lexer implements Twig_LexerInterface { - protected $cursor; - protected $position; - protected $end; - protected $pushedBack; - protected $code; - protected $lineno; - protected $filename; - protected $env; - protected $options; - - const POSITION_DATA = 0; - const POSITION_BLOCK = 1; - const POSITION_VAR = 2; - - const REGEX_NAME = '/[A-Za-z_][A-Za-z0-9_]*/A'; - const REGEX_NUMBER = '/[0-9]+(?:\.[0-9]+)?/A'; - const REGEX_STRING = '/(?:"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)"|\'([^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\')/Asm'; - const REGEX_OPERATOR = '/<=? | >=? | [!=]= | \/\/ | \.\. | [(){}.,%*\/+~|-] | \[ | \] | \? | \:/Ax'; - - public function __construct(Twig_Environment $env = null, array $options = array()) - { - $this->env = $env; - - $this->options = array_merge(array( - 'tag_comment' => array('{#', '#}'), - 'tag_block' => array('{%', '%}'), - 'tag_variable' => array('{{', '}}'), - ), $options); - } - - /** - * 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 = 'n/a') - { - if (function_exists('mb_internal_encoding') && ((int) ini_get('mbstring.func_overload')) & 2) + protected $cursor; + protected $position; + protected $end; + protected $pushedBack; + protected $code; + protected $lineno; + protected $filename; + protected $env; + protected $options; + + const POSITION_DATA = 0; + const POSITION_BLOCK = 1; + const POSITION_VAR = 2; + + const REGEX_NAME = '/[A-Za-z_][A-Za-z0-9_]*/A'; + const REGEX_NUMBER = '/[0-9]+(?:\.[0-9]+)?/A'; + const REGEX_STRING = '/(?:"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)"|\'([^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\')/Asm'; + const REGEX_OPERATOR = '/<=? | >=? | [!=]= | \/\/ | \.\. | [(){}.,%*\/+~|-] | \[ | \] | \? | \:/Ax'; + + public function __construct(Twig_Environment $env = null, array $options = array()) { - $mbEncoding = mb_internal_encoding(); - mb_internal_encoding('ASCII'); + $this->env = $env; + + $this->options = array_merge(array( + 'tag_comment' => array('{#', '#}'), + 'tag_block' => array('{%', '%}'), + 'tag_variable' => array('{{', '}}'), + ), $options); } - $this->code = str_replace(array("\r\n", "\r"), "\n", $code); - $this->filename = $filename; - $this->cursor = 0; - $this->lineno = 1; - $this->pushedBack = array(); - $this->end = strlen($this->code); - $this->position = self::POSITION_DATA; - - $tokens = array(); - $end = false; - while (!$end) + /** + * 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 = 'n/a') { - $token = $this->nextToken(); + if (function_exists('mb_internal_encoding') && ((int) ini_get('mbstring.func_overload')) & 2) { + $mbEncoding = mb_internal_encoding(); + mb_internal_encoding('ASCII'); + } - $tokens[] = $token; + $this->code = str_replace(array("\r\n", "\r"), "\n", $code); + $this->filename = $filename; + $this->cursor = 0; + $this->lineno = 1; + $this->pushedBack = array(); + $this->end = strlen($this->code); + $this->position = self::POSITION_DATA; - $end = $token->getType() === Twig_Token::EOF_TYPE; - } + $tokens = array(); + $end = false; + while (!$end) { + $token = $this->nextToken(); - if (isset($mbEncoding)) - { - mb_internal_encoding($mbEncoding); - } + $tokens[] = $token; - return new Twig_TokenStream($tokens, $this->filename, $this->env->getTrimBlocks()); - } - - public function setEnvironment(Twig_Environment $env) - { - $this->env = $env; - } - - /** - * Parses the next token and returns it. - */ - protected function nextToken() - { - // do we have tokens pushed back? get one - if (!empty($this->pushedBack)) - { - return array_shift($this->pushedBack); + $end = $token->getType() === Twig_Token::EOF_TYPE; + } + + if (isset($mbEncoding)) { + mb_internal_encoding($mbEncoding); + } + + return new Twig_TokenStream($tokens, $this->filename, $this->env->getTrimBlocks()); } - // have we reached the end of the code? - if ($this->cursor >= $this->end) + public function setEnvironment(Twig_Environment $env) { - return new Twig_Token(Twig_Token::EOF_TYPE, '', $this->lineno); + $this->env = $env; } - // otherwise dispatch to the lexing functions depending - // on our current position in the code. - switch ($this->position) + /** + * Parses the next token and returns it. + */ + protected function nextToken() { - case self::POSITION_DATA: - $tokens = $this->lexData(); - break; + // do we have tokens pushed back? get one + if (!empty($this->pushedBack)) { + return array_shift($this->pushedBack); + } - case self::POSITION_BLOCK: - $tokens = $this->lexBlock(); - break; + // have we reached the end of the code? + if ($this->cursor >= $this->end) { + return new Twig_Token(Twig_Token::EOF_TYPE, '', $this->lineno); + } - case self::POSITION_VAR: - $tokens = $this->lexVar(); - break; - } + // otherwise dispatch to the lexing functions depending + // on our current position in the code. + switch ($this->position) { + case self::POSITION_DATA: + $tokens = $this->lexData(); + break; - // if the return value is not an array it's a token - if (!is_array($tokens)) - { - return $tokens; - } - // empty array, call again - else if (empty($tokens)) - { - return $this->nextToken(); - } - // if we have multiple items we push them to the buffer - else if (count($tokens) > 1) - { - $first = array_shift($tokens); - $this->pushedBack = $tokens; + case self::POSITION_BLOCK: + $tokens = $this->lexBlock(); + break; - return $first; + case self::POSITION_VAR: + $tokens = $this->lexVar(); + break; + } + + // if the return value is not an array it's a token + if (!is_array($tokens)) { + return $tokens; + } + // empty array, call again + else if (empty($tokens)) { + return $this->nextToken(); + } + // if we have multiple items we push them to the buffer + else if (count($tokens) > 1) { + $first = array_shift($tokens); + $this->pushedBack = $tokens; + + return $first; + } + // otherwise return the first item of the array. + else { + return $tokens[0]; + } } - // otherwise return the first item of the array. - else + + protected function lexData() { - return $tokens[0]; - } - } + $match = null; - protected function lexData() - { - $match = null; + $pos1 = strpos($this->code, $this->options['tag_comment'][0], $this->cursor); + $pos2 = strpos($this->code, $this->options['tag_variable'][0], $this->cursor); + $pos3 = strpos($this->code, $this->options['tag_block'][0], $this->cursor); - $pos1 = strpos($this->code, $this->options['tag_comment'][0], $this->cursor); - $pos2 = strpos($this->code, $this->options['tag_variable'][0], $this->cursor); - $pos3 = strpos($this->code, $this->options['tag_block'][0], $this->cursor); + // if no matches are left we return the rest of the template + // as simple text token + if (false === $pos1 && false === $pos2 && false === $pos3) { + $rv = new Twig_Token(Twig_Token::TEXT_TYPE, substr($this->code, $this->cursor), $this->lineno); + $this->cursor = $this->end; - // if no matches are left we return the rest of the template - // as simple text token - if (false === $pos1 && false === $pos2 && false === $pos3) - { - $rv = new Twig_Token(Twig_Token::TEXT_TYPE, substr($this->code, $this->cursor), $this->lineno); - $this->cursor = $this->end; + return $rv; + } - return $rv; - } + // min + $pos = -log(0); + if (false !== $pos1 && $pos1 < $pos) { + $pos = $pos1; + $token = $this->options['tag_comment'][0]; + } + if (false !== $pos2 && $pos2 < $pos) { + $pos = $pos2; + $token = $this->options['tag_variable'][0]; + } + if (false !== $pos3 && $pos3 < $pos) { + $pos = $pos3; + $token = $this->options['tag_block'][0]; + } - // min - $pos = -log(0); - if (false !== $pos1 && $pos1 < $pos) - { - $pos = $pos1; - $token = $this->options['tag_comment'][0]; - } - if (false !== $pos2 && $pos2 < $pos) - { - $pos = $pos2; - $token = $this->options['tag_variable'][0]; - } - if (false !== $pos3 && $pos3 < $pos) - { - $pos = $pos3; - $token = $this->options['tag_block'][0]; - } + // update the lineno on the instance + $lineno = $this->lineno; - // update the lineno on the instance - $lineno = $this->lineno; + $text = substr($this->code, $this->cursor, $pos - $this->cursor); + $this->moveCursor($text.$token); + $this->moveLineNo($text.$token); - $text = substr($this->code, $this->cursor, $pos - $this->cursor); - $this->moveCursor($text.$token); - $this->moveLineNo($text.$token); + // array of tokens + $result = array(); - // array of tokens - $result = array(); + // push the template text first + if (!empty($text)) { + $result[] = new Twig_Token(Twig_Token::TEXT_TYPE, $text, $lineno); + $lineno += substr_count($text, "\n"); + } - // push the template text first - if (!empty($text)) - { - $result[] = new Twig_Token(Twig_Token::TEXT_TYPE, $text, $lineno); - $lineno += substr_count($text, "\n"); + switch ($token) { + case $this->options['tag_comment'][0]: + if (!preg_match('/(.*?)'.preg_quote($this->options['tag_comment'][1], '/').'/As', $this->code, $match, null, $this->cursor)) { + throw new Twig_SyntaxError('unclosed comment', $this->lineno, $this->filename); + } + $this->moveCursor($match[0]); + $this->moveLineNo($match[0]); + break; + + case $this->options['tag_block'][0]: + // raw data? + if (preg_match('/\s*raw\s*'.preg_quote($this->options['tag_block'][1], '/').'(.*?)'.preg_quote($this->options['tag_block'][0], '/').'\s*endraw\s*'.preg_quote($this->options['tag_block'][1], '/').'/As', $this->code, $match, null, $this->cursor)) { + $result[] = new Twig_Token(Twig_Token::TEXT_TYPE, $match[1], $lineno); + $this->moveCursor($match[0]); + $this->moveLineNo($match[0]); + $this->position = self::POSITION_DATA; + } else { + $result[] = new Twig_Token(Twig_Token::BLOCK_START_TYPE, '', $lineno); + $this->position = self::POSITION_BLOCK; + } + break; + + case $this->options['tag_variable'][0]: + $result[] = new Twig_Token(Twig_Token::VAR_START_TYPE, '', $lineno); + $this->position = self::POSITION_VAR; + break; + } + + return $result; } - switch ($token) + protected function lexBlock() { - case $this->options['tag_comment'][0]: - if (!preg_match('/(.*?)'.preg_quote($this->options['tag_comment'][1], '/').'/As', $this->code, $match, null, $this->cursor)) - { - throw new Twig_SyntaxError('unclosed comment', $this->lineno, $this->filename); - } - $this->moveCursor($match[0]); - $this->moveLineNo($match[0]); - break; - - case $this->options['tag_block'][0]: - // raw data? - if (preg_match('/\s*raw\s*'.preg_quote($this->options['tag_block'][1], '/').'(.*?)'.preg_quote($this->options['tag_block'][0], '/').'\s*endraw\s*'.preg_quote($this->options['tag_block'][1], '/').'/As', $this->code, $match, null, $this->cursor)) - { - $result[] = new Twig_Token(Twig_Token::TEXT_TYPE, $match[1], $lineno); - $this->moveCursor($match[0]); - $this->moveLineNo($match[0]); - $this->position = self::POSITION_DATA; - } - else - { - $result[] = new Twig_Token(Twig_Token::BLOCK_START_TYPE, '', $lineno); - $this->position = self::POSITION_BLOCK; + if (preg_match('/\s*'.preg_quote($this->options['tag_block'][1], '/').'/As', $this->code, $match, null, $this->cursor)) { + $lineno = $this->lineno; + $this->moveCursor($match[0]); + $this->moveLineNo($match[0]); + $this->position = self::POSITION_DATA; + + return new Twig_Token(Twig_Token::BLOCK_END_TYPE, '', $lineno); } - break; - case $this->options['tag_variable'][0]: - $result[] = new Twig_Token(Twig_Token::VAR_START_TYPE, '', $lineno); - $this->position = self::POSITION_VAR; - break; + return $this->lexExpression(); } - return $result; - } - - protected function lexBlock() - { - if (preg_match('/\s*'.preg_quote($this->options['tag_block'][1], '/').'/As', $this->code, $match, null, $this->cursor)) + protected function lexVar() { - $lineno = $this->lineno; - $this->moveCursor($match[0]); - $this->moveLineNo($match[0]); - $this->position = self::POSITION_DATA; + if (preg_match('/\s*'.preg_quote($this->options['tag_variable'][1], '/').'/As', $this->code, $match, null, $this->cursor)) { + $lineno = $this->lineno; + $this->moveCursor($match[0]); + $this->moveLineNo($match[0]); + $this->position = self::POSITION_DATA; - return new Twig_Token(Twig_Token::BLOCK_END_TYPE, '', $lineno); - } + return new Twig_Token(Twig_Token::VAR_END_TYPE, '', $lineno); + } - return $this->lexExpression(); - } + return $this->lexExpression(); + } - protected function lexVar() - { - if (preg_match('/\s*'.preg_quote($this->options['tag_variable'][1], '/').'/As', $this->code, $match, null, $this->cursor)) + protected function lexExpression() { - $lineno = $this->lineno; - $this->moveCursor($match[0]); - $this->moveLineNo($match[0]); - $this->position = self::POSITION_DATA; + $match = null; - return new Twig_Token(Twig_Token::VAR_END_TYPE, '', $lineno); - } + // whitespace + while (preg_match('/\s+/As', $this->code, $match, null, $this->cursor)) { + $this->moveCursor($match[0]); + $this->moveLineNo($match[0]); + } - return $this->lexExpression(); - } + // sanity check + if ($this->cursor >= $this->end) { + throw new Twig_SyntaxError('Unexpected end of stream', $this->lineno, $this->filename); + } - protected function lexExpression() - { - $match = null; + // first parse operators + if (preg_match(self::REGEX_OPERATOR, $this->code, $match, null, $this->cursor)) { + $this->moveCursor($match[0]); - // whitespace - while (preg_match('/\s+/As', $this->code, $match, null, $this->cursor)) - { - $this->moveCursor($match[0]); - $this->moveLineNo($match[0]); - } + return new Twig_Token(Twig_Token::OPERATOR_TYPE, $match[0], $this->lineno); + } + // now names + else if (preg_match(self::REGEX_NAME, $this->code, $match, null, $this->cursor)) { + $this->moveCursor($match[0]); - // sanity check - if ($this->cursor >= $this->end) - { - throw new Twig_SyntaxError('Unexpected end of stream', $this->lineno, $this->filename); - } + return new Twig_Token(Twig_Token::NAME_TYPE, $match[0], $this->lineno); + } + // then numbers + else if (preg_match(self::REGEX_NUMBER, $this->code, $match, null, $this->cursor)) { + $this->moveCursor($match[0]); + $value = (float)$match[0]; + if ((int)$value === $value) { + $value = (int)$value; + } + + return new Twig_Token(Twig_Token::NUMBER_TYPE, $value, $this->lineno); + } + // and finally strings + else if (preg_match(self::REGEX_STRING, $this->code, $match, null, $this->cursor)) { + $this->moveCursor($match[0]); + $this->moveLineNo($match[0]); + $value = stripcslashes(substr($match[0], 1, strlen($match[0]) - 2)); - // first parse operators - if (preg_match(self::REGEX_OPERATOR, $this->code, $match, null, $this->cursor)) - { - $this->moveCursor($match[0]); + return new Twig_Token(Twig_Token::STRING_TYPE, $value, $this->lineno); + } - return new Twig_Token(Twig_Token::OPERATOR_TYPE, $match[0], $this->lineno); + // unlexable + throw new Twig_SyntaxError(sprintf("Unexpected character '%s'", $this->code[$this->cursor]), $this->lineno, $this->filename); } - // now names - else if (preg_match(self::REGEX_NAME, $this->code, $match, null, $this->cursor)) - { - $this->moveCursor($match[0]); - return new Twig_Token(Twig_Token::NAME_TYPE, $match[0], $this->lineno); - } - // then numbers - else if (preg_match(self::REGEX_NUMBER, $this->code, $match, null, $this->cursor)) + protected function moveLineNo($text) { - $this->moveCursor($match[0]); - $value = (float)$match[0]; - if ((int)$value === $value) - { - $value = (int)$value; - } - - return new Twig_Token(Twig_Token::NUMBER_TYPE, $value, $this->lineno); + $this->lineno += substr_count($text, "\n"); } - // and finally strings - else if (preg_match(self::REGEX_STRING, $this->code, $match, null, $this->cursor)) - { - $this->moveCursor($match[0]); - $this->moveLineNo($match[0]); - $value = stripcslashes(substr($match[0], 1, strlen($match[0]) - 2)); - return new Twig_Token(Twig_Token::STRING_TYPE, $value, $this->lineno); + protected function moveCursor($text) + { + $this->cursor += strlen($text); } - // unlexable - throw new Twig_SyntaxError(sprintf("Unexpected character '%s'", $this->code[$this->cursor]), $this->lineno, $this->filename); - } - - protected function moveLineNo($text) - { - $this->lineno += substr_count($text, "\n"); - } - - protected function moveCursor($text) - { - $this->cursor += strlen($text); - } - } diff --git a/lib/Twig/LexerInterface.php b/lib/Twig/LexerInterface.php index 4ec1985..ddba3a1 100644 --- a/lib/Twig/LexerInterface.php +++ b/lib/Twig/LexerInterface.php @@ -18,13 +18,13 @@ */ interface Twig_LexerInterface { - /** - * 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 = 'n/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 = 'n/a'); } diff --git a/lib/Twig/Loader/Array.php b/lib/Twig/Loader/Array.php index c62f935..87aa7cd 100644 --- a/lib/Twig/Loader/Array.php +++ b/lib/Twig/Loader/Array.php @@ -23,66 +23,63 @@ */ class Twig_Loader_Array implements Twig_LoaderInterface { - protected $templates; + protected $templates; - /** - * 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) - { - $this->templates = array(); - foreach ($templates as $name => $template) + /** + * 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) { - $this->templates[$name] = $template; + $this->templates = array(); + foreach ($templates as $name => $template) { + $this->templates[$name] = $template; + } } - } - /** - * Gets the source code of a template, given its name. - * - * @param string $name string The name of the template to load - * - * @return string The template source code - */ - public function getSource($name) - { - if (!isset($this->templates[$name])) + /** + * Gets the source code of a template, given its name. + * + * @param string $name string The name of the template to load + * + * @return string The template source code + */ + public function getSource($name) { - throw new LogicException(sprintf('Template "%s" is not defined.', $name)); - } + if (!isset($this->templates[$name])) { + throw new LogicException(sprintf('Template "%s" is not defined.', $name)); + } - return $this->templates[$name]; - } + return $this->templates[$name]; + } - /** - * Gets the cache key to use for the cache for a given template name. - * - * @param string $name string The name of the template to load - * - * @return string The cache key - */ - public function getCacheKey($name) - { - if (!isset($this->templates[$name])) + /** + * Gets the cache key to use for the cache for a given template name. + * + * @param string $name string The name of the template to load + * + * @return string The cache key + */ + public function getCacheKey($name) { - throw new LogicException(sprintf('Template "%s" is not defined.', $name)); - } + if (!isset($this->templates[$name])) { + throw new LogicException(sprintf('Template "%s" is not defined.', $name)); + } - return $this->templates[$name]; - } + return $this->templates[$name]; + } - /** - * Returns true if the template is still fresh. - * - * @param string $name The template name - * @param timestamp $time The last modification time of the cached template - */ - public function isFresh($name, $time) - { - return true; - } + /** + * Returns true if the template is still fresh. + * + * @param string $name The template name + * @param timestamp $time The last modification time of the cached template + */ + public function isFresh($name, $time) + { + return true; + } } diff --git a/lib/Twig/Loader/Filesystem.php b/lib/Twig/Loader/Filesystem.php index c5face2..5d77183 100644 --- a/lib/Twig/Loader/Filesystem.php +++ b/lib/Twig/Loader/Filesystem.php @@ -18,116 +18,109 @@ */ class Twig_Loader_Filesystem implements Twig_LoaderInterface { - protected $paths; - protected $cache; - - /** - * Constructor. - * - * @param string|array $paths A path or an array of paths where to look for templates - */ - public function __construct($paths) - { - $this->setPaths($paths); - } - - /** - * Returns the paths to the templates. - * - * @return array The array of paths where to look for templates - */ - public function getPaths() - { - return $this->paths; - } - - /** - * Sets the paths where templates are stored. - * - * @param string|array $paths A path or an array of paths where to look for templates - */ - public function setPaths($paths) - { - // invalidate the cache - $this->cache = array(); - - if (!is_array($paths)) + protected $paths; + protected $cache; + + /** + * Constructor. + * + * @param string|array $paths A path or an array of paths where to look for templates + */ + public function __construct($paths) { - $paths = array($paths); + $this->setPaths($paths); } - $this->paths = array(); - foreach ($paths as $path) + /** + * Returns the paths to the templates. + * + * @return array The array of paths where to look for templates + */ + public function getPaths() { - if (!is_dir($path)) - { - throw new InvalidArgumentException(sprintf('The "%s" directory does not exist.', $path)); - } + return $this->paths; + } + + /** + * Sets the paths where templates are stored. + * + * @param string|array $paths A path or an array of paths where to look for templates + */ + public function setPaths($paths) + { + // invalidate the cache + $this->cache = array(); + + if (!is_array($paths)) { + $paths = array($paths); + } - $this->paths[] = realpath($path); + $this->paths = array(); + foreach ($paths as $path) { + if (!is_dir($path)) { + throw new InvalidArgumentException(sprintf('The "%s" directory does not exist.', $path)); + } + + $this->paths[] = realpath($path); + } } - } - - /** - * Gets the source code of a template, given its name. - * - * @param string $name string The name of the template to load - * - * @return string The template source code - */ - public function getSource($name) - { - return file_get_contents($this->findTemplate($name)); - } - - /** - * Gets the cache key to use for the cache for a given template name. - * - * @param string $name string The name of the template to load - * - * @return string The cache key - */ - public function getCacheKey($name) - { - return $this->findTemplate($name); - } - - /** - * Returns true if the template is still fresh. - * - * @param string $name The template name - * @param timestamp $time The last modification time of the cached template - */ - public function isFresh($name, $time) - { - return filemtime($this->findTemplate($name)) < $time; - } - - protected function findTemplate($name) - { - if (isset($this->cache[$name])) + + /** + * Gets the source code of a template, given its name. + * + * @param string $name string The name of the template to load + * + * @return string The template source code + */ + public function getSource($name) { - return $this->cache[$name]; + return file_get_contents($this->findTemplate($name)); } - foreach ($this->paths as $path) + /** + * Gets the cache key to use for the cache for a given template name. + * + * @param string $name string The name of the template to load + * + * @return string The cache key + */ + public function getCacheKey($name) { - if (!file_exists($path.DIRECTORY_SEPARATOR.$name)) - { - continue; - } + return $this->findTemplate($name); + } - $file = realpath($path.DIRECTORY_SEPARATOR.$name); + /** + * Returns true if the template is still fresh. + * + * @param string $name The template name + * @param timestamp $time The last modification time of the cached template + */ + public function isFresh($name, $time) + { + return filemtime($this->findTemplate($name)) < $time; + } + + protected function findTemplate($name) + { + if (isset($this->cache[$name])) { + return $this->cache[$name]; + } - // simple security check - if (0 !== strpos($file, $path)) - { - throw new RuntimeException('Looks like you try to load a template outside configured directories.'); - } + foreach ($this->paths as $path) { + if (!file_exists($path.DIRECTORY_SEPARATOR.$name)) { + continue; + } - return $this->cache[$name] = $file; - } + $file = realpath($path.DIRECTORY_SEPARATOR.$name); - throw new RuntimeException(sprintf('Unable to find template "%s" (looked into: %s).', $name, implode(', ', $this->paths))); - } + // simple security check + if (0 !== strpos($file, $path)) { + throw new RuntimeException('Looks like you try to load a template outside configured directories.'); + } + + return $this->cache[$name] = $file; + } + + throw new RuntimeException(sprintf('Unable to find template "%s" (looked into: %s).', $name, implode(', ', $this->paths))); + } } diff --git a/lib/Twig/Loader/String.php b/lib/Twig/Loader/String.php index 5fe451d..d31ea9e 100644 --- a/lib/Twig/Loader/String.php +++ b/lib/Twig/Loader/String.php @@ -23,38 +23,38 @@ */ class Twig_Loader_String implements Twig_LoaderInterface { - /** - * Gets the source code of a template, given its name. - * - * @param string $name string The name of the template to load - * - * @return string The template source code - */ - public function getSource($name) - { - return $name; - } + /** + * Gets the source code of a template, given its name. + * + * @param string $name string The name of the template to load + * + * @return string The template source code + */ + public function getSource($name) + { + return $name; + } - /** - * Gets the cache key to use for the cache for a given template name. - * - * @param string $name string The name of the template to load - * - * @return string The cache key - */ - public function getCacheKey($name) - { - return $name; - } + /** + * Gets the cache key to use for the cache for a given template name. + * + * @param string $name string The name of the template to load + * + * @return string The cache key + */ + public function getCacheKey($name) + { + return $name; + } - /** - * Returns true if the template is still fresh. - * - * @param string $name The template name - * @param timestamp $time The last modification time of the cached template - */ - public function isFresh($name, $time) - { - return true; - } + /** + * Returns true if the template is still fresh. + * + * @param string $name The template name + * @param timestamp $time The last modification time of the cached template + */ + public function isFresh($name, $time) + { + return true; + } } diff --git a/lib/Twig/LoaderInterface.php b/lib/Twig/LoaderInterface.php index fee97a0..d793f84 100644 --- a/lib/Twig/LoaderInterface.php +++ b/lib/Twig/LoaderInterface.php @@ -18,29 +18,29 @@ */ interface Twig_LoaderInterface { - /** - * Gets the source code of a template, given its name. - * - * @param string $name string The name of the template to load - * - * @return string The template source code - */ - public function getSource($name); + /** + * Gets the source code of a template, given its name. + * + * @param string $name string The name of the template to load + * + * @return string The template source code + */ + public function getSource($name); - /** - * Gets the cache key to use for the cache for a given template name. - * - * @param string $name string The name of the template to load - * - * @return string The cache key - */ - public function getCacheKey($name); + /** + * Gets the cache key to use for the cache for a given template name. + * + * @param string $name string The name of the template to load + * + * @return string The cache key + */ + public function getCacheKey($name); - /** - * Returns true if the template is still fresh. - * - * @param string $name The template name - * @param timestamp $time The last modification time of the cached template - */ - public function isFresh($name, $time); + /** + * Returns true if the template is still fresh. + * + * @param string $name The template name + * @param timestamp $time The last modification time of the cached template + */ + public function isFresh($name, $time); } diff --git a/lib/Twig/Node.php b/lib/Twig/Node.php index 366617e..538e202 100644 --- a/lib/Twig/Node.php +++ b/lib/Twig/Node.php @@ -19,29 +19,29 @@ */ abstract class Twig_Node { - protected $lineno; - protected $tag; + protected $lineno; + protected $tag; - public function __construct($lineno, $tag = null) - { - $this->lineno = $lineno; - $this->tag = $tag; - } + public function __construct($lineno, $tag = null) + { + $this->lineno = $lineno; + $this->tag = $tag; + } - public function __toString() - { - return get_class($this).'()'; - } + public function __toString() + { + return get_class($this).'()'; + } - abstract public function compile($compiler); + abstract public function compile($compiler); - public function getLine() - { - return $this->lineno; - } + public function getLine() + { + return $this->lineno; + } - public function getTag() - { - return $this->tag; - } + public function getTag() + { + return $this->tag; + } } diff --git a/lib/Twig/Node/AutoEscape.php b/lib/Twig/Node/AutoEscape.php index 98df7f7..01b9e0e 100644 --- a/lib/Twig/Node/AutoEscape.php +++ b/lib/Twig/Node/AutoEscape.php @@ -24,45 +24,44 @@ */ class Twig_Node_AutoEscape extends Twig_Node implements Twig_NodeListInterface { - protected $value; - protected $body; + protected $value; + protected $body; - public function __construct($value, Twig_NodeList $body, $lineno, $tag = null) - { - parent::__construct($lineno, $tag); - $this->value = $value; - $this->body = $body; - } - - public function __toString() - { - $repr = array(get_class($this).'('.($this->value ? 'on' : 'off')); - foreach (explode("\n", $this->body) as $line) + public function __construct($value, Twig_NodeList $body, $lineno, $tag = null) { - $repr[] = ' '.$line; + parent::__construct($lineno, $tag); + $this->value = $value; + $this->body = $body; } - $repr[] = ')'; - return implode("\n", $repr); - } + public function __toString() + { + $repr = array(get_class($this).'('.($this->value ? 'on' : 'off')); + foreach (explode("\n", $this->body) as $line) { + $repr[] = ' '.$line; + } + $repr[] = ')'; + + return implode("\n", $repr); + } - public function getNodes() - { - return $this->body->getNodes(); - } + public function getNodes() + { + return $this->body->getNodes(); + } - public function setNodes(array $nodes) - { - $this->body = new Twig_NodeList($nodes, $this->lineno); - } + public function setNodes(array $nodes) + { + $this->body = new Twig_NodeList($nodes, $this->lineno); + } - public function compile($compiler) - { - $compiler->subcompile($this->body); - } + public function compile($compiler) + { + $compiler->subcompile($this->body); + } - public function getValue() - { - return $this->value; - } + public function getValue() + { + return $this->value; + } } diff --git a/lib/Twig/Node/Block.php b/lib/Twig/Node/Block.php index 796a5c4..26f1b45 100644 --- a/lib/Twig/Node/Block.php +++ b/lib/Twig/Node/Block.php @@ -19,75 +19,73 @@ */ class Twig_Node_Block extends Twig_Node implements Twig_NodeListInterface { - protected $name; - protected $body; - protected $parent; + protected $name; + protected $body; + protected $parent; - public function __construct($name, Twig_NodeList $body, $lineno, $parent = null, $tag = null) - { - parent::__construct($lineno, $tag); - $this->name = $name; - $this->body = $body; - $this->parent = $parent; - } - - public function __toString() - { - $repr = array(get_class($this).' '.$this->name.'('); - foreach ($this->body->getNodes() as $node) + public function __construct($name, Twig_NodeList $body, $lineno, $parent = null, $tag = null) { - foreach (explode("\n", $node->__toString()) as $line) - { - $repr[] = ' '.$line; - } + parent::__construct($lineno, $tag); + $this->name = $name; + $this->body = $body; + $this->parent = $parent; } - $repr[] = ')'; - return implode("\n", $repr); - } + public function __toString() + { + $repr = array(get_class($this).' '.$this->name.'('); + foreach ($this->body->getNodes() as $node) { + foreach (explode("\n", $node->__toString()) as $line) { + $repr[] = ' '.$line; + } + } + $repr[] = ')'; - public function getNodes() - { - return $this->body->getNodes(); - } + return implode("\n", $repr); + } - public function setNodes(array $nodes) - { - $this->body = new Twig_NodeList($nodes, $this->lineno); - } + public function getNodes() + { + return $this->body->getNodes(); + } - public function replace($other) - { - $this->body = $other->body; - } + public function setNodes(array $nodes) + { + $this->body = new Twig_NodeList($nodes, $this->lineno); + } + + public function replace($other) + { + $this->body = $other->body; + } - public function compile($compiler) - { - $compiler - ->addDebugInfo($this) - ->write(sprintf("public function block_%s(\$context)\n", $this->name), "{\n") - ->indent() - ; + public function compile($compiler) + { + $compiler + ->addDebugInfo($this) + ->write(sprintf("public function block_%s(\$context)\n", $this->name), "{\n") + ->indent() + ; - $compiler - ->subcompile($this->body) - ->outdent() - ->write("}\n\n") - ; - } + $compiler + ->subcompile($this->body) + ->outdent() + ->write("}\n\n") + ; + } - public function getName() - { - return $this->name; - } + public function getName() + { + return $this->name; + } - public function getParent() - { - return $this->parent; - } + public function getParent() + { + return $this->parent; + } - public function setParent($parent) - { - $this->parent = $parent; - } + public function setParent($parent) + { + $this->parent = $parent; + } } diff --git a/lib/Twig/Node/BlockReference.php b/lib/Twig/Node/BlockReference.php index 3fadb78..f950c93 100644 --- a/lib/Twig/Node/BlockReference.php +++ b/lib/Twig/Node/BlockReference.php @@ -19,29 +19,29 @@ */ class Twig_Node_BlockReference extends Twig_Node { - protected $name; + protected $name; - public function __construct($name, $lineno, $tag = null) - { - parent::__construct($lineno, $tag); - $this->name = $name; - } + public function __construct($name, $lineno, $tag = null) + { + parent::__construct($lineno, $tag); + $this->name = $name; + } - public function __toString() - { - return get_class($this).'('.$this->name.')'; - } + public function __toString() + { + return get_class($this).'('.$this->name.')'; + } - public function compile($compiler) - { - $compiler - ->addDebugInfo($this) - ->write(sprintf('$this->block_%s($context);'."\n", $this->name)) - ; - } + public function compile($compiler) + { + $compiler + ->addDebugInfo($this) + ->write(sprintf('$this->block_%s($context);'."\n", $this->name)) + ; + } - public function getName() - { - return $this->name; - } + public function getName() + { + return $this->name; + } } diff --git a/lib/Twig/Node/Debug.php b/lib/Twig/Node/Debug.php index c8d7b31..2cf3af6 100644 --- a/lib/Twig/Node/Debug.php +++ b/lib/Twig/Node/Debug.php @@ -2,38 +2,35 @@ class Twig_Node_Debug extends Twig_Node { - protected $expr; + protected $expr; - public function __construct(Twig_Node_Expression $expr = null, $lineno, $tag = null) - { - parent::__construct($lineno, $tag); + public function __construct(Twig_Node_Expression $expr = null, $lineno, $tag = null) + { + parent::__construct($lineno, $tag); - $this->expr = $expr; - } + $this->expr = $expr; + } - public function compile($compiler) - { - $compiler->addDebugInfo($this); + public function compile($compiler) + { + $compiler->addDebugInfo($this); - $compiler - ->write("if (\$this->env->isDebug())\n", "{\n") - ->indent() - ->write('var_export(') - ; + $compiler + ->write("if (\$this->env->isDebug())\n", "{\n") + ->indent() + ->write('var_export(') + ; - if (null === $this->expr) - { - $compiler->raw('$context'); - } - else - { - $compiler->subcompile($this->expr); - } + if (null === $this->expr) { + $compiler->raw('$context'); + } else { + $compiler->subcompile($this->expr); + } - $compiler - ->raw(");\n") - ->outdent() - ->write("}\n") - ; - } + $compiler + ->raw(");\n") + ->outdent() + ->write("}\n") + ; + } } diff --git a/lib/Twig/Node/Expression/Array.php b/lib/Twig/Node/Expression/Array.php index 14cc49d..ba26b04 100644 --- a/lib/Twig/Node/Expression/Array.php +++ b/lib/Twig/Node/Expression/Array.php @@ -10,63 +10,59 @@ */ class Twig_Node_Expression_Array extends Twig_Node_Expression implements Twig_NodeListInterface { - protected $elements; + protected $elements; - public function __construct($elements, $lineno) - { - parent::__construct($lineno); + public function __construct($elements, $lineno) + { + parent::__construct($lineno); - $this->elements = $elements; - } + $this->elements = $elements; + } - public function __toString() - { - $repr = array(get_class($this).'('); - foreach ($this->elements as $name => $node) + public function __toString() { - foreach (explode("\n", ' '.$name.' => '.$node) as $line) - { - $repr[] = ' '.$line; - } - } - $repr[] = ')'; + $repr = array(get_class($this).'('); + foreach ($this->elements as $name => $node) { + foreach (explode("\n", ' '.$name.' => '.$node) as $line) { + $repr[] = ' '.$line; + } + } + $repr[] = ')'; - return implode("\n", $repr); - } + return implode("\n", $repr); + } - public function getNodes() - { - return $this->elements; - } + public function getNodes() + { + return $this->elements; + } - public function setNodes(array $nodes) - { - $this->elements = $nodes; - } + public function setNodes(array $nodes) + { + $this->elements = $nodes; + } - public function compile($compiler) - { - $compiler->raw('array('); - $first = true; - foreach ($this->elements as $name => $node) + public function compile($compiler) { - if (!$first) - { - $compiler->raw(', '); - } - $first = false; + $compiler->raw('array('); + $first = true; + foreach ($this->elements as $name => $node) { + if (!$first) { + $compiler->raw(', '); + } + $first = false; - $compiler - ->repr($name) - ->raw(' => ') - ->subcompile($node) - ; + $compiler + ->repr($name) + ->raw(' => ') + ->subcompile($node) + ; + } + $compiler->raw(')'); } - $compiler->raw(')'); - } - public function getElements() - { - return $this->elements; - } + public function getElements() + { + return $this->elements; + } } diff --git a/lib/Twig/Node/Expression/AssignName.php b/lib/Twig/Node/Expression/AssignName.php index eec3f99..0459e8b 100644 --- a/lib/Twig/Node/Expression/AssignName.php +++ b/lib/Twig/Node/Expression/AssignName.php @@ -12,8 +12,8 @@ class Twig_Node_Expression_AssignName extends Twig_Node_Expression_Name { - public function compile($compiler) - { - $compiler->raw(sprintf('$context[\'%s\']', $this->name)); - } + public function compile($compiler) + { + $compiler->raw(sprintf('$context[\'%s\']', $this->name)); + } } diff --git a/lib/Twig/Node/Expression/Binary.php b/lib/Twig/Node/Expression/Binary.php index dbe6757..41b1b3c 100644 --- a/lib/Twig/Node/Expression/Binary.php +++ b/lib/Twig/Node/Expression/Binary.php @@ -11,51 +11,49 @@ */ abstract class Twig_Node_Expression_Binary extends Twig_Node_Expression { - protected $left; - protected $right; + protected $left; + protected $right; - public function __construct(Twig_Node $left, Twig_Node $right, $lineno) - { - parent::__construct($lineno); - $this->left = $left; - $this->right = $right; - } - - public function __toString() - { - $repr = array(get_class($this).'('); - - foreach (explode("\n", $this->left->__toString()) as $line) + public function __construct(Twig_Node $left, Twig_Node $right, $lineno) { - $repr[] = ' '.$line; + parent::__construct($lineno); + $this->left = $left; + $this->right = $right; } - $repr[] = ', '; + public function __toString() + { + $repr = array(get_class($this).'('); + + foreach (explode("\n", $this->left->__toString()) as $line) { + $repr[] = ' '.$line; + } + + $repr[] = ', '; + + foreach (explode("\n", $this->right->__toString()) as $line) { + $repr[] = ' '.$line; + } + + $repr[] = ')'; + + return implode("\n", $repr); + } - foreach (explode("\n", $this->right->__toString()) as $line) + public function compile($compiler) { - $repr[] = ' '.$line; + $compiler + ->raw('(') + ->subcompile($this->left) + ->raw(') ') + ; + $this->operator($compiler); + $compiler + ->raw(' (') + ->subcompile($this->right) + ->raw(')') + ; } - $repr[] = ')'; - - return implode("\n", $repr); - } - - public function compile($compiler) - { - $compiler - ->raw('(') - ->subcompile($this->left) - ->raw(') ') - ; - $this->operator($compiler); - $compiler - ->raw(' (') - ->subcompile($this->right) - ->raw(')') - ; - } - - abstract public function operator($compiler); + abstract public function operator($compiler); } diff --git a/lib/Twig/Node/Expression/Binary/Add.php b/lib/Twig/Node/Expression/Binary/Add.php index 63bc0a2..df0712a 100644 --- a/lib/Twig/Node/Expression/Binary/Add.php +++ b/lib/Twig/Node/Expression/Binary/Add.php @@ -11,8 +11,8 @@ */ class Twig_Node_Expression_Binary_Add extends Twig_Node_Expression_Binary { - public function operator($compiler) - { - return $compiler->raw('+'); - } + public function operator($compiler) + { + return $compiler->raw('+'); + } } diff --git a/lib/Twig/Node/Expression/Binary/And.php b/lib/Twig/Node/Expression/Binary/And.php index 1fe4bc3..8cecf44 100644 --- a/lib/Twig/Node/Expression/Binary/And.php +++ b/lib/Twig/Node/Expression/Binary/And.php @@ -11,8 +11,8 @@ */ class Twig_Node_Expression_Binary_And extends Twig_Node_Expression_Binary { - public function operator($compiler) - { - return $compiler->raw('&&'); - } + public function operator($compiler) + { + return $compiler->raw('&&'); + } } diff --git a/lib/Twig/Node/Expression/Binary/Concat.php b/lib/Twig/Node/Expression/Binary/Concat.php index 61e6954..573dea8 100644 --- a/lib/Twig/Node/Expression/Binary/Concat.php +++ b/lib/Twig/Node/Expression/Binary/Concat.php @@ -11,8 +11,8 @@ */ class Twig_Node_Expression_Binary_Concat extends Twig_Node_Expression_Binary { - public function operator($compiler) - { - return $compiler->raw('.'); - } + public function operator($compiler) + { + return $compiler->raw('.'); + } } diff --git a/lib/Twig/Node/Expression/Binary/Div.php b/lib/Twig/Node/Expression/Binary/Div.php index 7361b73..d481e5d 100644 --- a/lib/Twig/Node/Expression/Binary/Div.php +++ b/lib/Twig/Node/Expression/Binary/Div.php @@ -11,8 +11,8 @@ */ class Twig_Node_Expression_Binary_Div extends Twig_Node_Expression_Binary { - public function operator($compiler) - { - return $compiler->raw('/'); - } + public function operator($compiler) + { + return $compiler->raw('/'); + } } diff --git a/lib/Twig/Node/Expression/Binary/FloorDiv.php b/lib/Twig/Node/Expression/Binary/FloorDiv.php index 2a9be20..6db622c 100644 --- a/lib/Twig/Node/Expression/Binary/FloorDiv.php +++ b/lib/Twig/Node/Expression/Binary/FloorDiv.php @@ -10,19 +10,19 @@ */ class Twig_Node_Expression_Binary_FloorDiv extends Twig_Node_Expression_Binary { - public function compile($compiler) - { - $compiler - ->raw('floor(') - ->subcompile($this->left) - ->raw(' / ') - ->subcompile($this->right) - ->raw(')') - ; - } + public function compile($compiler) + { + $compiler + ->raw('floor(') + ->subcompile($this->left) + ->raw(' / ') + ->subcompile($this->right) + ->raw(')') + ; + } - public function operator($compiler) - { - return; - } + public function operator($compiler) + { + return; + } } diff --git a/lib/Twig/Node/Expression/Binary/Mod.php b/lib/Twig/Node/Expression/Binary/Mod.php index e2c9117..da20b1b 100644 --- a/lib/Twig/Node/Expression/Binary/Mod.php +++ b/lib/Twig/Node/Expression/Binary/Mod.php @@ -11,8 +11,8 @@ */ class Twig_Node_Expression_Binary_Mod extends Twig_Node_Expression_Binary { - public function operator($compiler) - { - return $compiler->raw('%'); - } + public function operator($compiler) + { + return $compiler->raw('%'); + } } diff --git a/lib/Twig/Node/Expression/Binary/Mul.php b/lib/Twig/Node/Expression/Binary/Mul.php index a236101..d6ecd57 100644 --- a/lib/Twig/Node/Expression/Binary/Mul.php +++ b/lib/Twig/Node/Expression/Binary/Mul.php @@ -11,8 +11,8 @@ */ class Twig_Node_Expression_Binary_Mul extends Twig_Node_Expression_Binary { - public function operator($compiler) - { - return $compiler->raw('*'); - } + public function operator($compiler) + { + return $compiler->raw('*'); + } } diff --git a/lib/Twig/Node/Expression/Binary/Or.php b/lib/Twig/Node/Expression/Binary/Or.php index a968b82..c4d733a 100644 --- a/lib/Twig/Node/Expression/Binary/Or.php +++ b/lib/Twig/Node/Expression/Binary/Or.php @@ -11,8 +11,8 @@ */ class Twig_Node_Expression_Binary_Or extends Twig_Node_Expression_Binary { - public function operator($compiler) - { - return $compiler->raw('||'); - } + public function operator($compiler) + { + return $compiler->raw('||'); + } } diff --git a/lib/Twig/Node/Expression/Binary/Sub.php b/lib/Twig/Node/Expression/Binary/Sub.php index f67117b..ede0f1e 100644 --- a/lib/Twig/Node/Expression/Binary/Sub.php +++ b/lib/Twig/Node/Expression/Binary/Sub.php @@ -11,8 +11,8 @@ */ class Twig_Node_Expression_Binary_Sub extends Twig_Node_Expression_Binary { - public function operator($compiler) - { - return $compiler->raw('-'); - } + public function operator($compiler) + { + return $compiler->raw('-'); + } } diff --git a/lib/Twig/Node/Expression/Compare.php b/lib/Twig/Node/Expression/Compare.php index 273380a..8d0774f 100644 --- a/lib/Twig/Node/Expression/Compare.php +++ b/lib/Twig/Node/Expression/Compare.php @@ -11,63 +11,56 @@ */ class Twig_Node_Expression_Compare extends Twig_Node_Expression { - protected $expr; - protected $ops; + protected $expr; + protected $ops; - public function __construct(Twig_Node_Expression $expr, $ops, $lineno) - { - parent::__construct($lineno); - $this->expr = $expr; - $this->ops = $ops; - } - - public function compile($compiler) - { - $nbOps = count($this->ops) > 1; - if ('in' === $this->ops[0][0]) + public function __construct(Twig_Node_Expression $expr, $ops, $lineno) { - return $this->compileIn($compiler); + parent::__construct($lineno); + $this->expr = $expr; + $this->ops = $ops; } - $this->expr->compile($compiler); - $i = 0; - foreach ($this->ops as $op) + public function compile($compiler) { - if ($i) - { - $compiler->raw(' && ($tmp'.$i); - } - list($op, $node) = $op; - $compiler->raw(' '.$op.' '); + $nbOps = count($this->ops) > 1; + if ('in' === $this->ops[0][0]) { + return $this->compileIn($compiler); + } - if ($nbOps) - { - $compiler - ->raw('($tmp'.++$i.' = ') - ->subcompile($node) - ->raw(')') - ; - } - else - { - $compiler->subcompile($node); - } + $this->expr->compile($compiler); + $i = 0; + foreach ($this->ops as $op) { + if ($i) { + $compiler->raw(' && ($tmp'.$i); + } + list($op, $node) = $op; + $compiler->raw(' '.$op.' '); + + if ($nbOps) { + $compiler + ->raw('($tmp'.++$i.' = ') + ->subcompile($node) + ->raw(')') + ; + } else { + $compiler->subcompile($node); + } + } + + for ($j = 1; $j < $i; $j++) { + $compiler->raw(')'); + } } - for ($j = 1; $j < $i; $j++) + protected function compileIn($compiler) { - $compiler->raw(')'); + $compiler + ->raw('twig_in_filter(') + ->subcompile($this->expr) + ->raw(', ') + ->subcompile($this->ops[0][1]) + ->raw(')') + ; } - } - - protected function compileIn($compiler) - { - $compiler - ->raw('twig_in_filter(') - ->subcompile($this->expr) - ->raw(', ') - ->subcompile($this->ops[0][1]) - ->raw(')') - ; - } } diff --git a/lib/Twig/Node/Expression/Conditional.php b/lib/Twig/Node/Expression/Conditional.php index d89d639..c04d111 100644 --- a/lib/Twig/Node/Expression/Conditional.php +++ b/lib/Twig/Node/Expression/Conditional.php @@ -11,28 +11,28 @@ */ class Twig_Node_Expression_Conditional extends Twig_Node_Expression { - protected $expr1; - protected $expr2; - protected $expr3; + protected $expr1; + protected $expr2; + protected $expr3; - public function __construct(Twig_Node_Expression $expr1, Twig_Node_Expression $expr2, Twig_Node_Expression $expr3, $lineno) - { - parent::__construct($lineno); - $this->expr1 = $expr1; - $this->expr2 = $expr2; - $this->expr3 = $expr3; - } + public function __construct(Twig_Node_Expression $expr1, Twig_Node_Expression $expr2, Twig_Node_Expression $expr3, $lineno) + { + parent::__construct($lineno); + $this->expr1 = $expr1; + $this->expr2 = $expr2; + $this->expr3 = $expr3; + } - public function compile($compiler) - { - $compiler - ->raw('(') - ->subcompile($this->expr1) - ->raw(') ? (') - ->subcompile($this->expr2) - ->raw(') : (') - ->subcompile($this->expr3) - ->raw(')') - ; - } + public function compile($compiler) + { + $compiler + ->raw('(') + ->subcompile($this->expr1) + ->raw(') ? (') + ->subcompile($this->expr2) + ->raw(') : (') + ->subcompile($this->expr3) + ->raw(')') + ; + } } diff --git a/lib/Twig/Node/Expression/Constant.php b/lib/Twig/Node/Expression/Constant.php index 976b381..533b218 100644 --- a/lib/Twig/Node/Expression/Constant.php +++ b/lib/Twig/Node/Expression/Constant.php @@ -11,26 +11,26 @@ */ class Twig_Node_Expression_Constant extends Twig_Node_Expression { - protected $value; + protected $value; - public function __construct($value, $lineno) - { - parent::__construct($lineno); - $this->value = $value; - } + public function __construct($value, $lineno) + { + parent::__construct($lineno); + $this->value = $value; + } - public function __toString() - { - return get_class($this).'('.$this->value.')'; - } + public function __toString() + { + return get_class($this).'('.$this->value.')'; + } - public function compile($compiler) - { - $compiler->repr($this->value); - } + public function compile($compiler) + { + $compiler->repr($this->value); + } - public function getValue() - { - return $this->value; - } + public function getValue() + { + return $this->value; + } } diff --git a/lib/Twig/Node/Expression/Filter.php b/lib/Twig/Node/Expression/Filter.php index 50eb41c..f8d63b0 100644 --- a/lib/Twig/Node/Expression/Filter.php +++ b/lib/Twig/Node/Expression/Filter.php @@ -11,118 +11,108 @@ */ class Twig_Node_Expression_Filter extends Twig_Node_Expression implements Twig_NodeListInterface { - protected $node; - protected $filters; + protected $node; + protected $filters; - public function __construct(Twig_Node $node, array $filters, $lineno, $tag = null) - { - parent::__construct($lineno, $tag); + public function __construct(Twig_Node $node, array $filters, $lineno, $tag = null) + { + parent::__construct($lineno, $tag); - $this->node = $node; - $this->filters = $filters; - } + $this->node = $node; + $this->filters = $filters; + } - public function __toString() - { - $filters = array(); - foreach ($this->filters as $filter) + public function __toString() { - $filters[] = $filter[0].'('.implode(', ', $filter[1]).')'; - } + $filters = array(); + foreach ($this->filters as $filter) { + $filters[] = $filter[0].'('.implode(', ', $filter[1]).')'; + } - $repr = array(get_class($this).'('.implode(', ', $filters)); + $repr = array(get_class($this).'('.implode(', ', $filters)); - foreach (explode("\n", $this->node->__toString()) as $line) - { - $repr[] = ' '.$line; + foreach (explode("\n", $this->node->__toString()) as $line) { + $repr[] = ' '.$line; + } + + $repr[] = ')'; + + return implode("\n", $repr); } - $repr[] = ')'; + public function getNodes() + { + return array($this->node); + } - return implode("\n", $repr); - } + public function setNodes(array $nodes) + { + $this->node = $nodes[0]; + } - public function getNodes() - { - return array($this->node); - } + public function compile($compiler) + { + $filterMap = $compiler->getEnvironment()->getFilters(); + + $postponed = array(); + for ($i = count($this->filters) - 1; $i >= 0; --$i) { + list($name, $attrs) = $this->filters[$i]; + if (!isset($filterMap[$name])) { + $compiler + ->raw('$this->resolveMissingFilter(') + ->repr($name) + ->raw(', ') + ; + } else { + $compiler->raw($filterMap[$name]->compile().($filterMap[$name]->needsEnvironment() ? '($this->getEnvironment(), ' : '(')); + } + $postponed[] = $attrs; + } + $this->node->compile($compiler); + foreach (array_reverse($postponed) as $attributes) { + foreach ($attributes as $node) { + $compiler + ->raw(', ') + ->subcompile($node) + ; + } + $compiler->raw(')'); + } + } - public function setNodes(array $nodes) - { - $this->node = $nodes[0]; - } + public function getFilters() + { + return $this->filters; + } - public function compile($compiler) - { - $filterMap = $compiler->getEnvironment()->getFilters(); + public function setFilters(array $filters) + { + $this->filters = $filters; + } - $postponed = array(); - for ($i = count($this->filters) - 1; $i >= 0; --$i) + public function prependFilter($filter) { - list($name, $attrs) = $this->filters[$i]; - if (!isset($filterMap[$name])) - { - $compiler - ->raw('$this->resolveMissingFilter(') - ->repr($name) - ->raw(', ') - ; - } - else - { - $compiler->raw($filterMap[$name]->compile().($filterMap[$name]->needsEnvironment() ? '($this->getEnvironment(), ' : '(')); - } - $postponed[] = $attrs; + $this->filters = array_merge(array($filter), $this->filters); } - $this->node->compile($compiler); - foreach (array_reverse($postponed) as $attributes) + + public function appendFilter($filter) { - foreach ($attributes as $node) - { - $compiler - ->raw(', ') - ->subcompile($node) - ; - } - $compiler->raw(')'); + $this->filters[] = $filter; } - } - - public function getFilters() - { - return $this->filters; - } - - public function setFilters(array $filters) - { - $this->filters = $filters; - } - - public function prependFilter($filter) - { - $this->filters = array_merge(array($filter), $this->filters); - } - - public function appendFilter($filter) - { - $this->filters[] = $filter; - } - - public function appendFilters(array $filters) - { - $this->filters = array_merge($this->filters, $filters); - } - - public function hasFilter($name) - { - foreach ($this->filters as $filter) + + public function appendFilters(array $filters) { - if ($name == $filter[0]) - { - return true; - } + $this->filters = array_merge($this->filters, $filters); } - return false; - } + public function hasFilter($name) + { + foreach ($this->filters as $filter) { + if ($name == $filter[0]) { + return true; + } + } + + return false; + } } diff --git a/lib/Twig/Node/Expression/GetAttr.php b/lib/Twig/Node/Expression/GetAttr.php index f396b38..7c7c9cc 100644 --- a/lib/Twig/Node/Expression/GetAttr.php +++ b/lib/Twig/Node/Expression/GetAttr.php @@ -11,64 +11,63 @@ */ class Twig_Node_Expression_GetAttr extends Twig_Node_Expression implements Twig_NodeListInterface { - protected $node; - protected $attr; - protected $arguments; + protected $node; + protected $attr; + protected $arguments; - public function __construct(Twig_Node $node, $attr, $arguments, $lineno, $token_value) - { - parent::__construct($lineno); - $this->node = $node; - $this->attr = $attr; - $this->arguments = $arguments; - $this->token_value = $token_value; - } - - public function __toString() - { - return get_class($this).'('.$this->node.', '.$this->attr.')'; - } - - public function getNode() - { - return $this->node; - } - - public function getNodes() - { - return array($this->node); - } - - public function setNodes(array $nodes) - { - $this->node = $nodes[0]; - } + public function __construct(Twig_Node $node, $attr, $arguments, $lineno, $token_value) + { + parent::__construct($lineno); + $this->node = $node; + $this->attr = $attr; + $this->arguments = $arguments; + $this->token_value = $token_value; + } - public function compile($compiler) - { - $compiler - ->raw('$this->getAttribute(') - ->subcompile($this->node) - ->raw(', ') - ->subcompile($this->attr) - ->raw(', array(') - ; + public function __toString() + { + return get_class($this).'('.$this->node.', '.$this->attr.')'; + } - foreach ($this->arguments as $node) + public function getNode() { - $compiler - ->subcompile($node) - ->raw(', ') - ; + return $this->node; } - $compiler->raw(')'); + public function getNodes() + { + return array($this->node); + } - if ('[' == $this->token_value) // Don't look for functions if they're using foo[bar] + public function setNodes(array $nodes) { - $compiler->raw(', true'); + $this->node = $nodes[0]; } - $compiler->raw(')'); - } + public function compile($compiler) + { + $compiler + ->raw('$this->getAttribute(') + ->subcompile($this->node) + ->raw(', ') + ->subcompile($this->attr) + ->raw(', array(') + ; + + foreach ($this->arguments as $node) { + $compiler + ->subcompile($node) + ->raw(', ') + ; + } + + $compiler->raw(')'); + + // Don't look for functions if they're using foo[bar] + if ('[' == $this->token_value) { + $compiler->raw(', true'); + } + + $compiler->raw(')'); + } } diff --git a/lib/Twig/Node/Expression/Name.php b/lib/Twig/Node/Expression/Name.php index 439a4b3..b4a8e41 100644 --- a/lib/Twig/Node/Expression/Name.php +++ b/lib/Twig/Node/Expression/Name.php @@ -11,26 +11,26 @@ */ class Twig_Node_Expression_Name extends Twig_Node_Expression { - protected $name; + protected $name; - public function __construct($name, $lineno) - { - parent::__construct($lineno); - $this->name = $name; - } + public function __construct($name, $lineno) + { + parent::__construct($lineno); + $this->name = $name; + } - public function __toString() - { - return get_class($this).'('.$this->name.')'; - } + public function __toString() + { + return get_class($this).'('.$this->name.')'; + } - public function compile($compiler) - { - $compiler->raw(sprintf('(isset($context[\'%s\']) ? $context[\'%s\'] : null)', $this->name, $this->name)); - } + public function compile($compiler) + { + $compiler->raw(sprintf('(isset($context[\'%s\']) ? $context[\'%s\'] : null)', $this->name, $this->name)); + } - public function getName() - { - return $this->name; - } + public function getName() + { + return $this->name; + } } diff --git a/lib/Twig/Node/Expression/Unary.php b/lib/Twig/Node/Expression/Unary.php index 652c7f6..416e846 100644 --- a/lib/Twig/Node/Expression/Unary.php +++ b/lib/Twig/Node/Expression/Unary.php @@ -11,34 +11,33 @@ */ abstract class Twig_Node_Expression_Unary extends Twig_Node_Expression { - protected $node; + protected $node; - public function __construct(Twig_Node $node, $lineno) - { - parent::__construct($lineno); - $this->node = $node; - } - - public function __toString() - { - $repr = array(get_class($this).'('); - - foreach (explode("\n", $this->node->__toString()) as $line) + public function __construct(Twig_Node $node, $lineno) { - $repr[] = ' '.$line; + parent::__construct($lineno); + $this->node = $node; } - $repr[] = ')'; + public function __toString() + { + $repr = array(get_class($this).'('); + + foreach (explode("\n", $this->node->__toString()) as $line) { + $repr[] = ' '.$line; + } - return implode("\n", $repr); - } - public function compile($compiler) - { - $compiler->raw('('); - $this->operator($compiler); - $this->node->compile($compiler); - $compiler->raw(')'); - } + $repr[] = ')'; + + return implode("\n", $repr); + } + public function compile($compiler) + { + $compiler->raw('('); + $this->operator($compiler); + $this->node->compile($compiler); + $compiler->raw(')'); + } - abstract public function operator($compiler); + abstract public function operator($compiler); } diff --git a/lib/Twig/Node/Expression/Unary/Neg.php b/lib/Twig/Node/Expression/Unary/Neg.php index 7893619..699ff06 100644 --- a/lib/Twig/Node/Expression/Unary/Neg.php +++ b/lib/Twig/Node/Expression/Unary/Neg.php @@ -11,8 +11,8 @@ */ class Twig_Node_Expression_Unary_Neg extends Twig_Node_Expression_Unary { - public function operator($compiler) - { - $compiler->raw('-'); - } + public function operator($compiler) + { + $compiler->raw('-'); + } } diff --git a/lib/Twig/Node/Expression/Unary/Not.php b/lib/Twig/Node/Expression/Unary/Not.php index 2771a23..47d83c7 100644 --- a/lib/Twig/Node/Expression/Unary/Not.php +++ b/lib/Twig/Node/Expression/Unary/Not.php @@ -11,8 +11,8 @@ */ class Twig_Node_Expression_Unary_Not extends Twig_Node_Expression_Unary { - public function operator($compiler) - { - $compiler->raw('!'); - } + public function operator($compiler) + { + $compiler->raw('!'); + } } diff --git a/lib/Twig/Node/Expression/Unary/Pos.php b/lib/Twig/Node/Expression/Unary/Pos.php index 40cec40..90865fe 100644 --- a/lib/Twig/Node/Expression/Unary/Pos.php +++ b/lib/Twig/Node/Expression/Unary/Pos.php @@ -11,8 +11,8 @@ */ class Twig_Node_Expression_Unary_Pos extends Twig_Node_Expression_Unary { - public function operator($compiler) - { - $compiler->raw('+'); - } + public function operator($compiler) + { + $compiler->raw('+'); + } } diff --git a/lib/Twig/Node/Filter.php b/lib/Twig/Node/Filter.php index 040a4d3..20a5b5c 100644 --- a/lib/Twig/Node/Filter.php +++ b/lib/Twig/Node/Filter.php @@ -18,53 +18,51 @@ */ class Twig_Node_Filter extends Twig_Node implements Twig_NodeListInterface { - protected $filters; - protected $body; + protected $filters; + protected $body; - public function __construct($filters, Twig_NodeList $body, $lineno, $tag = null) - { - parent::__construct($lineno, $tag); - $this->filters = $filters; - $this->body = $body; - } - - public function __toString() - { - $filters = array(); - foreach ($this->filters as $filter) + public function __construct($filters, Twig_NodeList $body, $lineno, $tag = null) { - $filters[] = $filter[0].'('.implode(', ', $filter[1]).')'; + parent::__construct($lineno, $tag); + $this->filters = $filters; + $this->body = $body; } - $repr = array(get_class($this).'('.implode(', ', $filters)); - - foreach (explode("\n", $this->body->__toString()) as $line) + public function __toString() { - $repr[] = ' '.$line; - } + $filters = array(); + foreach ($this->filters as $filter) { + $filters[] = $filter[0].'('.implode(', ', $filter[1]).')'; + } + + $repr = array(get_class($this).'('.implode(', ', $filters)); - $repr[] = ')'; + foreach (explode("\n", $this->body->__toString()) as $line) { + $repr[] = ' '.$line; + } - return implode("\n", $repr); - } + $repr[] = ')'; - public function getNodes() - { - return $this->body->getNodes(); - } + return implode("\n", $repr); + } + + public function getNodes() + { + return $this->body->getNodes(); + } - public function setNodes(array $nodes) - { - $this->body = new Twig_NodeList($nodes, $this->lineno); - } + public function setNodes(array $nodes) + { + $this->body = new Twig_NodeList($nodes, $this->lineno); + } - public function compile($compiler) - { - $compiler->subcompile($this->body); - } + public function compile($compiler) + { + $compiler->subcompile($this->body); + } - public function getFilters() - { - return $this->filters; - } + public function getFilters() + { + return $this->filters; + } } diff --git a/lib/Twig/Node/For.php b/lib/Twig/Node/For.php index 50b0408..a86c35c 100644 --- a/lib/Twig/Node/For.php +++ b/lib/Twig/Node/For.php @@ -19,130 +19,122 @@ */ class Twig_Node_For extends Twig_Node implements Twig_NodeListInterface { - protected $isMultitarget; - protected $item; - protected $seq; - protected $body; - protected $else; - protected $withLoop; - - public function __construct($isMultitarget, $item, $seq, Twig_NodeList $body, Twig_Node $else = null, $withLoop = false, $lineno, $tag = null) - { - parent::__construct($lineno, $tag); - $this->isMultitarget = $isMultitarget; - $this->item = $item; - $this->seq = $seq; - $this->body = $body; - $this->else = $else; - $this->withLoop = $withLoop; - $this->lineno = $lineno; - } - - public function getNodes() - { - return $this->body->getNodes(); - } - - public function setNodes(array $nodes) - { - $this->body = new Twig_NodeList($nodes, $this->lineno); - } - - public function compile($compiler) - { - $compiler - ->addDebugInfo($this) - ->pushContext() - ; - - if (!is_null($this->else)) + protected $isMultitarget; + protected $item; + protected $seq; + protected $body; + protected $else; + protected $withLoop; + + public function __construct($isMultitarget, $item, $seq, Twig_NodeList $body, Twig_Node $else = null, $withLoop = false, $lineno, $tag = null) { - $compiler->write("\$context['_iterated'] = false;\n"); + parent::__construct($lineno, $tag); + $this->isMultitarget = $isMultitarget; + $this->item = $item; + $this->seq = $seq; + $this->body = $body; + $this->else = $else; + $this->withLoop = $withLoop; + $this->lineno = $lineno; } - if ($this->isMultitarget) + public function getNodes() { - $loopVars = array($this->item[0]->getName(), $this->item[1]->getName()); + return $this->body->getNodes(); } - else - { - $loopVars = array('_key', $this->item->getName()); - } - - $compiler - ->write("\$context['_seq'] = twig_iterator_to_array(") - ->subcompile($this->seq) - ->raw(");\n") - ; - if ($this->withLoop) + public function setNodes(array $nodes) { - $compiler - ->write("\$length = count(\$context['_seq']);\n") - - ->write("\$context['loop'] = array(\n") - ->write(" 'parent' => \$context['_parent'],\n") - ->write(" 'length' => \$length,\n") - ->write(" 'index0' => 0,\n") - ->write(" 'index' => 1,\n") - ->write(" 'revindex0' => \$length - 1,\n") - ->write(" 'revindex' => \$length,\n") - ->write(" 'first' => true,\n") - ->write(" 'last' => 1 === \$length,\n") - ->write(");\n") - ; + $this->body = new Twig_NodeList($nodes, $this->lineno); } - $compiler - ->write("foreach (\$context['_seq'] as \$context[") - ->repr($loopVars[0]) - ->raw("] => \$context[") - ->repr($loopVars[1]) - ->raw("])\n") - ->write("{\n") - ->indent() - ; - - if (!is_null($this->else)) + public function compile($compiler) { - $compiler->write("\$context['_iterated'] = true;\n"); + $compiler + ->addDebugInfo($this) + ->pushContext() + ; + + if (!is_null($this->else)) { + $compiler->write("\$context['_iterated'] = false;\n"); + } + + if ($this->isMultitarget) { + $loopVars = array($this->item[0]->getName(), $this->item[1]->getName()); + } else { + $loopVars = array('_key', $this->item->getName()); + } + + $compiler + ->write("\$context['_seq'] = twig_iterator_to_array(") + ->subcompile($this->seq) + ->raw(");\n") + ; + + if ($this->withLoop) { + $compiler + ->write("\$length = count(\$context['_seq']);\n") + + ->write("\$context['loop'] = array(\n") + ->write(" 'parent' => \$context['_parent'],\n") + ->write(" 'length' => \$length,\n") + ->write(" 'index0' => 0,\n") + ->write(" 'index' => 1,\n") + ->write(" 'revindex0' => \$length - 1,\n") + ->write(" 'revindex' => \$length,\n") + ->write(" 'first' => true,\n") + ->write(" 'last' => 1 === \$length,\n") + ->write(");\n") + ; + } + + $compiler + ->write("foreach (\$context['_seq'] as \$context[") + ->repr($loopVars[0]) + ->raw("] => \$context[") + ->repr($loopVars[1]) + ->raw("])\n") + ->write("{\n") + ->indent() + ; + + if (!is_null($this->else)) { + $compiler->write("\$context['_iterated'] = true;\n"); + } + + $compiler->subcompile($this->body); + + if ($this->withLoop) { + $compiler + ->write("++\$context['loop']['index0'];\n") + ->write("++\$context['loop']['index'];\n") + ->write("--\$context['loop']['revindex0'];\n") + ->write("--\$context['loop']['revindex'];\n") + ->write("\$context['loop']['first'] = false;\n") + ->write("\$context['loop']['last'] = 0 === \$context['loop']['revindex0'];\n") + ; + } + + $compiler + ->outdent() + ->write("}\n") + ; + + if (!is_null($this->else)) { + $compiler + ->write("if (!\$context['_iterated'])\n") + ->write("{\n") + ->indent() + ->subcompile($this->else) + ->outdent() + ->write("}\n") + ; + } + $compiler->popContext(); } - $compiler->subcompile($this->body); - - if ($this->withLoop) + public function setWithLoop($boolean) { - $compiler - ->write("++\$context['loop']['index0'];\n") - ->write("++\$context['loop']['index'];\n") - ->write("--\$context['loop']['revindex0'];\n") - ->write("--\$context['loop']['revindex'];\n") - ->write("\$context['loop']['first'] = false;\n") - ->write("\$context['loop']['last'] = 0 === \$context['loop']['revindex0'];\n") - ; + $this->withLoop = (Boolean) $boolean; } - - $compiler - ->outdent() - ->write("}\n") - ; - - if (!is_null($this->else)) - { - $compiler - ->write("if (!\$context['_iterated'])\n") - ->write("{\n") - ->indent() - ->subcompile($this->else) - ->outdent() - ->write("}\n") - ; - } - $compiler->popContext(); - } - - public function setWithLoop($boolean) - { - $this->withLoop = (Boolean) $boolean; - } } diff --git a/lib/Twig/Node/If.php b/lib/Twig/Node/If.php index 6763ee7..587b5e7 100644 --- a/lib/Twig/Node/If.php +++ b/lib/Twig/Node/If.php @@ -19,108 +19,95 @@ */ class Twig_Node_If extends Twig_Node implements Twig_NodeListInterface { - protected $tests; - protected $else; + protected $tests; + protected $else; - public function __construct($tests, Twig_NodeList $else = null, $lineno, $tag = null) - { - parent::__construct($lineno, $tag); - $this->tests = $tests; - $this->else = $else; - } - - public function __toString() - { - $repr = array(get_class($this).'('); - foreach ($this->tests as $test) + public function __construct($tests, Twig_NodeList $else = null, $lineno, $tag = null) { - foreach (explode("\n", $test[0].' => '.$test[1]) as $line) - { - $repr[] = ' '.$line; - } + parent::__construct($lineno, $tag); + $this->tests = $tests; + $this->else = $else; } - $repr[] = ')'; - if ($this->else) + public function __toString() { - foreach (explode("\n", $this->else) as $line) - { - $repr[] = ' '.$line; - } - } + $repr = array(get_class($this).'('); + foreach ($this->tests as $test) { + foreach (explode("\n", $test[0].' => '.$test[1]) as $line) { + $repr[] = ' '.$line; + } + } + $repr[] = ')'; - return implode("\n", $repr); - } + if ($this->else) { + foreach (explode("\n", $this->else) as $line) { + $repr[] = ' '.$line; + } + } - public function getNodes() - { - $nodes = array(); - foreach ($this->tests as $test) - { - $nodes[] = $test[1]; + return implode("\n", $repr); } - if ($this->else) + public function getNodes() { - $nodes[] = $this->else; - } + $nodes = array(); + foreach ($this->tests as $test) { + $nodes[] = $test[1]; + } - return $nodes; - } + if ($this->else) { + $nodes[] = $this->else; + } - public function setNodes(array $nodes) - { - foreach ($this->tests as $i => $test) - { - $this->tests[$i][1] = $nodes[$i]; + return $nodes; } - if ($this->else) + public function setNodes(array $nodes) { - $nodes = $nodes[count($nodes) - 1]; + foreach ($this->tests as $i => $test) { + $this->tests[$i][1] = $nodes[$i]; + } + + if ($this->else) { + $nodes = $nodes[count($nodes) - 1]; + } } - } - public function compile($compiler) - { - $compiler->addDebugInfo($this); - $idx = 0; - foreach ($this->tests as $test) + public function compile($compiler) { - if ($idx++) - { - $compiler - ->outdent() - ->write("}\n", "elseif (") - ; - } - else - { - $compiler - ->write('if (') - ; - } + $compiler->addDebugInfo($this); + $idx = 0; + foreach ($this->tests as $test) { + if ($idx++) { + $compiler + ->outdent() + ->write("}\n", "elseif (") + ; + } else { + $compiler + ->write('if (') + ; + } - $compiler - ->subcompile($test[0]) - ->raw(")\n") - ->write("{\n") - ->indent() - ->subcompile($test[1]) - ; - } - if (!is_null($this->else)) - { - $compiler - ->outdent() - ->write("}\n", "else\n", "{\n") - ->indent() - ->subcompile($this->else) - ; - } + $compiler + ->subcompile($test[0]) + ->raw(")\n") + ->write("{\n") + ->indent() + ->subcompile($test[1]) + ; + } + if (!is_null($this->else)) { + $compiler + ->outdent() + ->write("}\n", "else\n", "{\n") + ->indent() + ->subcompile($this->else) + ; + } - $compiler - ->outdent() - ->write("}\n"); - } + $compiler + ->outdent() + ->write("}\n"); + } } diff --git a/lib/Twig/Node/Import.php b/lib/Twig/Node/Import.php index 8978839..6237c94 100644 --- a/lib/Twig/Node/Import.php +++ b/lib/Twig/Node/Import.php @@ -18,49 +18,49 @@ */ class Twig_Node_Import extends Twig_Node { - protected $macro; - protected $var; + protected $macro; + protected $var; - public function __construct($macro, $var, $lineno, $tag = null) - { - parent::__construct($lineno, $tag); - $this->macro = $macro; - $this->var = $var; - } + public function __construct($macro, $var, $lineno, $tag = null) + { + parent::__construct($lineno, $tag); + $this->macro = $macro; + $this->var = $var; + } - public function __toString() - { - return get_class($this).'('.$this->macro.', '.$this->var.')'; - } + public function __toString() + { + return get_class($this).'('.$this->macro.', '.$this->var.')'; + } - public function compile($compiler) - { - $compiler - ->addDebugInfo($this) - ->write('$this->env->loadTemplate(') - ->string($this->macro) - ->raw(");\n\n") - ->write("if (!class_exists(") - ->string($compiler->getTemplateClass($this->macro).'_Macro') - ->raw("))\n") - ->write("{\n") - ->indent() - ->write(sprintf("throw new InvalidArgumentException('There is no defined macros in template \"%s\".');\n", $this->macro)) - ->outdent() - ->write("}\n") - ->write(sprintf("\$context[")) - ->string($this->var) - ->raw(sprintf("] = new %s_Macro(\$this->env);\n", $compiler->getTemplateClass($this->macro))) - ; - } + public function compile($compiler) + { + $compiler + ->addDebugInfo($this) + ->write('$this->env->loadTemplate(') + ->string($this->macro) + ->raw(");\n\n") + ->write("if (!class_exists(") + ->string($compiler->getTemplateClass($this->macro).'_Macro') + ->raw("))\n") + ->write("{\n") + ->indent() + ->write(sprintf("throw new InvalidArgumentException('There is no defined macros in template \"%s\".');\n", $this->macro)) + ->outdent() + ->write("}\n") + ->write(sprintf("\$context[")) + ->string($this->var) + ->raw(sprintf("] = new %s_Macro(\$this->env);\n", $compiler->getTemplateClass($this->macro))) + ; + } - public function getMacro() - { - return $this->macro; - } + public function getMacro() + { + return $this->macro; + } - public function getVar() - { - return $this->var; - } + public function getVar() + { + return $this->var; + } } diff --git a/lib/Twig/Node/Include.php b/lib/Twig/Node/Include.php index 0da7d2f..85b8593 100644 --- a/lib/Twig/Node/Include.php +++ b/lib/Twig/Node/Include.php @@ -19,109 +19,97 @@ */ class Twig_Node_Include extends Twig_Node implements Twig_NodeListInterface { - protected $expr; - protected $sandboxed; - protected $variables; - - public function __construct(Twig_Node_Expression $expr, $sandboxed, $variables, $lineno, $tag = null) - { - parent::__construct($lineno, $tag); - - $this->expr = $expr; - $this->sandboxed = $sandboxed; - $this->variables = $variables; - } - - public function __toString() - { - return get_class($this).'('.$this->expr.')'; - } - - public function getNodes() - { - if (null === $this->variables) - { - return array(new Twig_Node_Text('', -1)); - } - else + protected $expr; + protected $sandboxed; + protected $variables; + + public function __construct(Twig_Node_Expression $expr, $sandboxed, $variables, $lineno, $tag = null) { - return array($this->variables); - } + parent::__construct($lineno, $tag); - return $this->variables->getNodes(); - } + $this->expr = $expr; + $this->sandboxed = $sandboxed; + $this->variables = $variables; + } - public function setNodes(array $nodes) - { - if (isset($nodes[0]) && -1 === $nodes[0]->getLine()) + public function __toString() { - $this->variables = null; + return get_class($this).'('.$this->expr.')'; } - else + + public function getNodes() { - $this->variables = $nodes[0]; + if (null === $this->variables) { + return array(new Twig_Node_Text('', -1)); + } else { + return array($this->variables); + } + + return $this->variables->getNodes(); } - } - - public function getIncludedFile() - { - return $this->expr; - } - - public function isSandboxed() - { - return $this->sandboxed; - } - - public function getVariables() - { - return $this->variables; - } - - public function compile($compiler) - { - if (!$compiler->getEnvironment()->hasExtension('sandbox') && $this->sandboxed) + + public function setNodes(array $nodes) { - throw new Twig_SyntaxError('Unable to use the sanboxed attribute on an include if the sandbox extension is not enabled.', $this->lineno); + if (isset($nodes[0]) && -1 === $nodes[0]->getLine()) { + $this->variables = null; + } else { + $this->variables = $nodes[0]; + } } - $compiler->addDebugInfo($this); - - if ($this->sandboxed) + public function getIncludedFile() { - $compiler - ->write("\$sandbox = \$this->env->getExtension('sandbox');\n") - ->write("\$alreadySandboxed = \$sandbox->isSandboxed();\n") - ->write("\$sandbox->enableSandbox();\n") - ; + return $this->expr; } - $compiler - ->write('$this->env->loadTemplate(') - ->subcompile($this->expr) - ->raw(')->display(') - ; - - if (null === $this->variables) + public function isSandboxed() { - $compiler->raw('$context'); + return $this->sandboxed; } - else + + public function getVariables() { - $compiler->subcompile($this->variables); + return $this->variables; } - $compiler->raw(");\n"); - - if ($this->sandboxed) + public function compile($compiler) { - $compiler - ->write("if (!\$alreadySandboxed)\n", "{\n") - ->indent() - ->write("\$sandbox->disableSandbox();\n") - ->outdent() - ->write("}\n") - ; + if (!$compiler->getEnvironment()->hasExtension('sandbox') && $this->sandboxed) { + throw new Twig_SyntaxError('Unable to use the sanboxed attribute on an include if the sandbox extension is not enabled.', $this->lineno); + } + + $compiler->addDebugInfo($this); + + if ($this->sandboxed) { + $compiler + ->write("\$sandbox = \$this->env->getExtension('sandbox');\n") + ->write("\$alreadySandboxed = \$sandbox->isSandboxed();\n") + ->write("\$sandbox->enableSandbox();\n") + ; + } + + $compiler + ->write('$this->env->loadTemplate(') + ->subcompile($this->expr) + ->raw(')->display(') + ; + + if (null === $this->variables) { + $compiler->raw('$context'); + } else { + $compiler->subcompile($this->variables); + } + + $compiler->raw(");\n"); + + if ($this->sandboxed) { + $compiler + ->write("if (!\$alreadySandboxed)\n", "{\n") + ->indent() + ->write("\$sandbox->disableSandbox();\n") + ->outdent() + ->write("}\n") + ; + } } - } } diff --git a/lib/Twig/Node/Macro.php b/lib/Twig/Node/Macro.php index eccc918..3f62e3c 100644 --- a/lib/Twig/Node/Macro.php +++ b/lib/Twig/Node/Macro.php @@ -18,80 +18,76 @@ */ class Twig_Node_Macro extends Twig_Node implements Twig_NodeListInterface { - protected $name; - protected $body; - protected $arguments; + protected $name; + protected $body; + protected $arguments; - public function __construct($name, Twig_NodeList $body, $arguments, $lineno, $parent = null, $tag = null) - { - parent::__construct($lineno, $tag); - $this->name = $name; - $this->body = $body; - $this->arguments = $arguments; - } - - public function __toString() - { - $repr = array(get_class($this).' '.$this->name.'('); - foreach ($this->body->getNodes() as $node) + public function __construct($name, Twig_NodeList $body, $arguments, $lineno, $parent = null, $tag = null) { - foreach (explode("\n", $node->__toString()) as $line) - { - $repr[] = ' '.$line; - } + parent::__construct($lineno, $tag); + $this->name = $name; + $this->body = $body; + $this->arguments = $arguments; } - $repr[] = ')'; - - return implode("\n", $repr); - } - - public function getNodes() - { - return $this->body->getNodes(); - } - public function setNodes(array $nodes) - { - $this->body = new Twig_NodeList($nodes, $this->lineno); - } + public function __toString() + { + $repr = array(get_class($this).' '.$this->name.'('); + foreach ($this->body->getNodes() as $node) { + foreach (explode("\n", $node->__toString()) as $line) { + $repr[] = ' '.$line; + } + } + $repr[] = ')'; - public function replace($other) - { - $this->body = $other->body; - } + return implode("\n", $repr); + } - public function compile($compiler) - { - $arguments = array(); - foreach ($this->arguments as $argument) + public function getNodes() { - $arguments[] = '$'.$argument->getName().' = null'; + return $this->body->getNodes(); } - $compiler - ->addDebugInfo($this) - ->write(sprintf("public function get%s(%s)\n", $this->name, implode(', ', $arguments)), "{\n") - ->indent() - ->write("\$context = array(\n") - ->indent() - ; + public function setNodes(array $nodes) + { + $this->body = new Twig_NodeList($nodes, $this->lineno); + } - foreach ($this->arguments as $argument) + public function replace($other) { - $compiler - ->write('') - ->string($argument->getName()) - ->raw(' => $'.$argument->getName()) - ->raw(",\n") - ; + $this->body = $other->body; } - $compiler - ->outdent() - ->write(");\n\n") - ->subcompile($this->body) - ->outdent() - ->write("}\n\n") - ; - } + public function compile($compiler) + { + $arguments = array(); + foreach ($this->arguments as $argument) { + $arguments[] = '$'.$argument->getName().' = null'; + } + + $compiler + ->addDebugInfo($this) + ->write(sprintf("public function get%s(%s)\n", $this->name, implode(', ', $arguments)), "{\n") + ->indent() + ->write("\$context = array(\n") + ->indent() + ; + + foreach ($this->arguments as $argument) { + $compiler + ->write('') + ->string($argument->getName()) + ->raw(' => $'.$argument->getName()) + ->raw(",\n") + ; + } + + $compiler + ->outdent() + ->write(");\n\n") + ->subcompile($this->body) + ->outdent() + ->write("}\n\n") + ; + } } diff --git a/lib/Twig/Node/Module.php b/lib/Twig/Node/Module.php index 7d0e555..3bbca1b 100644 --- a/lib/Twig/Node/Module.php +++ b/lib/Twig/Node/Module.php @@ -19,252 +19,230 @@ */ class Twig_Node_Module extends Twig_Node implements Twig_NodeListInterface { - protected $body; - protected $extends; - protected $blocks; - protected $macros; - protected $filename; - protected $usedFilters; - protected $usedTags; - - public function __construct(Twig_NodeList $body, $extends, array $blocks, array $macros, $filename) - { - parent::__construct(1); - - $this->body = $body; - $this->extends = $extends; - $this->blocks = array_values($blocks); - $this->macros = $macros; - $this->filename = $filename; - $this->usedFilters = array(); - $this->usedTags = array(); - } - - public function __toString() - { - $repr = array(get_class($this).'(', ' body:'); - foreach ($this->body->getNodes() as $node) + protected $body; + protected $extends; + protected $blocks; + protected $macros; + protected $filename; + protected $usedFilters; + protected $usedTags; + + public function __construct(Twig_NodeList $body, $extends, array $blocks, array $macros, $filename) { - foreach (explode("\n", $node->__toString()) as $line) - { - $repr[] = ' '.$line; - } + parent::__construct(1); + + $this->body = $body; + $this->extends = $extends; + $this->blocks = array_values($blocks); + $this->macros = $macros; + $this->filename = $filename; + $this->usedFilters = array(); + $this->usedTags = array(); } - $repr[] = ' blocks: '; - foreach ($this->blocks as $node) + public function __toString() { - foreach (explode("\n", $node->__toString()) as $line) - { - $repr[] = ' '.$line; - } - } - - $repr[] = ' macros: '; - foreach ($this->macros as $node) - { - foreach (explode("\n", $node->__toString()) as $line) - { - $repr[] = ' '.$line; - } - } - - $repr[] = ')'; + $repr = array(get_class($this).'(', ' body:'); + foreach ($this->body->getNodes() as $node) { + foreach (explode("\n", $node->__toString()) as $line) { + $repr[] = ' '.$line; + } + } - return implode("\n", $repr); - } + $repr[] = ' blocks: '; + foreach ($this->blocks as $node) { + foreach (explode("\n", $node->__toString()) as $line) { + $repr[] = ' '.$line; + } + } - public function getFilename() - { - return $this->filename; - } + $repr[] = ' macros: '; + foreach ($this->macros as $node) { + foreach (explode("\n", $node->__toString()) as $line) { + $repr[] = ' '.$line; + } + } - public function getBody() - { - return $this->body; - } + $repr[] = ')'; - public function getNodes() - { - return array_merge(array($this->body), $this->blocks, $this->macros); - } + return implode("\n", $repr); + } - public function setNodes(array $nodes) - { - $this->body = array_shift($nodes); - $this->blocks = array(); - $this->macros = array(); - foreach ($nodes as $node) + public function getFilename() { - if ($node instanceof Twig_Node_Macro) - { - $this->macros[] = $node; - } - else - { - $this->blocks[] = $node; - } + return $this->filename; } - } - - public function setUsedFilters(array $filters) - { - $this->usedFilters = $filters; - } - public function setUsedTags(array $tags) - { - $this->usedTags = $tags; - } - - public function compile($compiler) - { - $this->compileTemplate($compiler); - $this->compileMacros($compiler); - } - - protected function compileTemplate($compiler) - { - $sandboxed = $compiler->getEnvironment()->hasExtension('sandbox'); - - $compiler->write("extends)) + public function getBody() { - $compiler - ->write('$this->loadTemplate(') - ->repr($this->extends) - ->raw(");\n\n") - ; + return $this->body; } - $compiler - // if the filename contains */, add a blank to avoid a PHP parse error - ->write("/* ".str_replace('*/', '* /', $this->filename)." */\n") - ->write('class '.$compiler->getTemplateClass($this->filename)) - ; - - $parent = null === $this->extends ? $compiler->getEnvironment()->getBaseTemplateClass() : $compiler->getTemplateClass($this->extends); - - $compiler - ->raw(" extends $parent\n") - ->write("{\n") - ->indent() - ->write("public function display(array \$context)\n", "{\n") - ->indent() - ; + public function getNodes() + { + return array_merge(array($this->body), $this->blocks, $this->macros); + } - if (null !== $this->extends) + public function setNodes(array $nodes) { - // remove all but import nodes - $nodes = array(); - foreach ($this->body->getNodes() as $node) - { - if ($node instanceof Twig_Node_Import) - { - $nodes[] = $node; + $this->body = array_shift($nodes); + $this->blocks = array(); + $this->macros = array(); + foreach ($nodes as $node) { + if ($node instanceof Twig_Node_Macro) { + $this->macros[] = $node; + } else { + $this->blocks[] = $node; + } } - } - - $compiler - ->subcompile(new Twig_NodeList($nodes)) - ->write("\n") - ->write("parent::display(\$context);\n") - ->outdent() - ->write("}\n\n") - ; } - else + + public function setUsedFilters(array $filters) { - if ($sandboxed) - { - $compiler->write("\$this->checkSecurity();\n"); - } - - $compiler - ->subcompile($this->body) - ->outdent() - ->write("}\n\n") - ; + $this->usedFilters = $filters; } - // blocks - foreach ($this->blocks as $node) + public function setUsedTags(array $tags) { - $compiler->subcompile($node); + $this->usedTags = $tags; } - if ($sandboxed) + public function compile($compiler) { - // sandbox information - $compiler - ->write("protected function checkSecurity()\n", "{\n") - ->indent() - ->write("\$this->env->getExtension('sandbox')->checkSecurity(\n") - ->indent() - ->write(!$this->usedTags ? "array(),\n" : "array('".implode('\', \'', $this->usedTags)."'),\n") - ->write(!$this->usedFilters ? "array()\n" : "array('".implode('\', \'', $this->usedFilters)."')\n") - ->outdent() - ->write(");\n") - ->outdent() - ->write("}\n\n") - ; + $this->compileTemplate($compiler); + $this->compileMacros($compiler); } - // debug information - if ($compiler->getEnvironment()->isDebug()) + protected function compileTemplate($compiler) { - $compiler - ->write("public function __toString()\n", "{\n") - ->indent() - ->write('return ') - ->string($this) - ->raw(";\n") - ->outdent() - ->write("}\n\n") - ; + $sandboxed = $compiler->getEnvironment()->hasExtension('sandbox'); + + $compiler->write("extends)) { + $compiler + ->write('$this->loadTemplate(') + ->repr($this->extends) + ->raw(");\n\n") + ; + } + + $compiler + // if the filename contains */, add a blank to avoid a PHP parse error + ->write("/* ".str_replace('*/', '* /', $this->filename)." */\n") + ->write('class '.$compiler->getTemplateClass($this->filename)) + ; + + $parent = null === $this->extends ? $compiler->getEnvironment()->getBaseTemplateClass() : $compiler->getTemplateClass($this->extends); + + $compiler + ->raw(" extends $parent\n") + ->write("{\n") + ->indent() + ->write("public function display(array \$context)\n", "{\n") + ->indent() + ; + + if (null !== $this->extends) { + // remove all but import nodes + $nodes = array(); + foreach ($this->body->getNodes() as $node) { + if ($node instanceof Twig_Node_Import) { + $nodes[] = $node; + } + } + + $compiler + ->subcompile(new Twig_NodeList($nodes)) + ->write("\n") + ->write("parent::display(\$context);\n") + ->outdent() + ->write("}\n\n") + ; + } else { + if ($sandboxed) { + $compiler->write("\$this->checkSecurity();\n"); + } + + $compiler + ->subcompile($this->body) + ->outdent() + ->write("}\n\n") + ; + } + + // blocks + foreach ($this->blocks as $node) { + $compiler->subcompile($node); + } + + if ($sandboxed) { + // sandbox information + $compiler + ->write("protected function checkSecurity()\n", "{\n") + ->indent() + ->write("\$this->env->getExtension('sandbox')->checkSecurity(\n") + ->indent() + ->write(!$this->usedTags ? "array(),\n" : "array('".implode('\', \'', $this->usedTags)."'),\n") + ->write(!$this->usedFilters ? "array()\n" : "array('".implode('\', \'', $this->usedFilters)."')\n") + ->outdent() + ->write(");\n") + ->outdent() + ->write("}\n\n") + ; + } + + // debug information + if ($compiler->getEnvironment()->isDebug()) { + $compiler + ->write("public function __toString()\n", "{\n") + ->indent() + ->write('return ') + ->string($this) + ->raw(";\n") + ->outdent() + ->write("}\n\n") + ; + } + + // original template name + $compiler + ->write("public function getName()\n", "{\n") + ->indent() + ->write('return ') + ->string($this->filename) + ->raw(";\n") + ->outdent() + ->write("}\n\n") + ; + + $compiler + ->outdent() + ->write("}\n") + ; } - // original template name - $compiler - ->write("public function getName()\n", "{\n") - ->indent() - ->write('return ') - ->string($this->filename) - ->raw(";\n") - ->outdent() - ->write("}\n\n") - ; - - $compiler - ->outdent() - ->write("}\n") - ; - } - - protected function compileMacros($compiler) - { - if (!$this->macros) + protected function compileMacros($compiler) { - return; - } + if (!$this->macros) { + return; + } - $compiler - ->write("\n") - ->write('class '.$compiler->getTemplateClass($this->filename).'_Macro extends Twig_Macro'."\n") - ->write("{\n") - ->indent() - ; + $compiler + ->write("\n") + ->write('class '.$compiler->getTemplateClass($this->filename).'_Macro extends Twig_Macro'."\n") + ->write("{\n") + ->indent() + ; - // macros - foreach ($this->macros as $node) - { - $compiler->subcompile($node); - } + // macros + foreach ($this->macros as $node) { + $compiler->subcompile($node); + } - $compiler - ->outdent() - ->write("}\n") - ; - } + $compiler + ->outdent() + ->write("}\n") + ; + } } diff --git a/lib/Twig/Node/Parent.php b/lib/Twig/Node/Parent.php index 0e83be1..076e9a2 100644 --- a/lib/Twig/Node/Parent.php +++ b/lib/Twig/Node/Parent.php @@ -19,24 +19,24 @@ */ class Twig_Node_Parent extends Twig_Node { - protected $blockName; + protected $blockName; - public function __construct($blockName, $lineno, $tag = null) - { - parent::__construct($lineno, $tag); - $this->blockName = $blockName; - } + public function __construct($blockName, $lineno, $tag = null) + { + parent::__construct($lineno, $tag); + $this->blockName = $blockName; + } - public function __toString() - { - return get_class($this).'('.$this->blockName.')'; - } + public function __toString() + { + return get_class($this).'('.$this->blockName.')'; + } - public function compile($compiler) - { - $compiler - ->addDebugInfo($this) - ->write('parent::block_'.$this->blockName.'($context);'."\n") - ; - } + public function compile($compiler) + { + $compiler + ->addDebugInfo($this) + ->write('parent::block_'.$this->blockName.'($context);'."\n") + ; + } } diff --git a/lib/Twig/Node/Print.php b/lib/Twig/Node/Print.php index df4a6ae..62edd87 100644 --- a/lib/Twig/Node/Print.php +++ b/lib/Twig/Node/Print.php @@ -19,48 +19,47 @@ */ class Twig_Node_Print extends Twig_Node implements Twig_NodeListInterface { - protected $expr; + protected $expr; - public function __construct(Twig_Node_Expression $expr, $lineno, $tag = null) - { - parent::__construct($lineno, $tag); - $this->expr = $expr; - } - - public function __toString() - { - $repr = array(get_class($this).'('); - foreach (explode("\n", $this->expr->__toString()) as $line) + public function __construct(Twig_Node_Expression $expr, $lineno, $tag = null) { - $repr[] = ' '.$line; + parent::__construct($lineno, $tag); + $this->expr = $expr; } - $repr[] = ')'; - return implode("\n", $repr); - } + public function __toString() + { + $repr = array(get_class($this).'('); + foreach (explode("\n", $this->expr->__toString()) as $line) { + $repr[] = ' '.$line; + } + $repr[] = ')'; + + return implode("\n", $repr); + } - public function getNodes() - { - return array($this->expr); - } + public function getNodes() + { + return array($this->expr); + } - public function setNodes(array $nodes) - { - $this->expr = $nodes[0]; - } + public function setNodes(array $nodes) + { + $this->expr = $nodes[0]; + } - public function compile($compiler) - { - $compiler - ->addDebugInfo($this) - ->write('echo ') - ->subcompile($this->expr) - ->raw(";\n") - ; - } + public function compile($compiler) + { + $compiler + ->addDebugInfo($this) + ->write('echo ') + ->subcompile($this->expr) + ->raw(";\n") + ; + } - public function getExpression() - { - return $this->expr; - } + public function getExpression() + { + return $this->expr; + } } diff --git a/lib/Twig/Node/Set.php b/lib/Twig/Node/Set.php index 7058b3f..6df66bb 100644 --- a/lib/Twig/Node/Set.php +++ b/lib/Twig/Node/Set.php @@ -18,126 +18,108 @@ */ class Twig_Node_Set extends Twig_Node implements Twig_NodeListInterface { - protected $names; - protected $values; - protected $isMultitarget; - protected $capture; - - public function __construct($isMultitarget, $capture, $names, $values, $lineno, $tag = null) - { - parent::__construct($lineno, $tag); - - $this->isMultitarget = $isMultitarget; - $this->capture = $capture; - $this->names = $names; - $this->values = $values; - } - - public function __toString() - { - $repr = array(get_class($this).'('.($this->isMultitarget ? implode(', ', $this->names) : $this->names).','); - foreach ($this->isMultitarget ? $this->values : array($this->values) as $node) - { - foreach (explode("\n", $node->__toString()) as $line) - { - $repr[] = ' '.$line; - } - } - $repr[] = ')'; - - return implode("\n", $repr); - } + protected $names; + protected $values; + protected $isMultitarget; + protected $capture; - public function getNodes() - { - if ($this->isMultitarget) - { - return $this->values; - } - else + public function __construct($isMultitarget, $capture, $names, $values, $lineno, $tag = null) { - return array($this->values); + parent::__construct($lineno, $tag); + + $this->isMultitarget = $isMultitarget; + $this->capture = $capture; + $this->names = $names; + $this->values = $values; } - } - public function setNodes(array $nodes) - { - $this->values = $this->isMultitarget ? $nodes : $nodes[0]; - } + public function __toString() + { + $repr = array(get_class($this).'('.($this->isMultitarget ? implode(', ', $this->names) : $this->names).','); + foreach ($this->isMultitarget ? $this->values : array($this->values) as $node) { + foreach (explode("\n", $node->__toString()) as $line) { + $repr[] = ' '.$line; + } + } + $repr[] = ')'; - public function compile($compiler) - { - $compiler->addDebugInfo($this); + return implode("\n", $repr); + } - if ($this->isMultitarget) + public function getNodes() { - $compiler->write('list('); - foreach ($this->names as $idx => $node) - { - if ($idx) - { - $compiler->raw(', '); + if ($this->isMultitarget) { + return $this->values; + } else { + return array($this->values); } - - $compiler - ->raw('$context[') - ->string($node->getName()) - ->raw(']') - ; - } - $compiler->raw(')'); } - else + + public function setNodes(array $nodes) { - if ($this->capture) - { - $compiler - ->write("ob_start();\n") - ->subcompile($this->values) - ; - } - - $compiler - ->write('$context[') - ->string($this->names->getName()) - ->raw(']') - ; - - if ($this->capture) - { - $compiler->raw(" = ob_get_clean()"); - } + $this->values = $this->isMultitarget ? $nodes : $nodes[0]; } - if (!$this->capture) + public function compile($compiler) { - $compiler->raw(' = '); - - if ($this->isMultitarget) - { - $compiler->write('array('); - foreach ($this->values as $idx => $value) - { - if ($idx) - { - $compiler->raw(', '); - } - - $compiler->subcompile($value); + $compiler->addDebugInfo($this); + + if ($this->isMultitarget) { + $compiler->write('list('); + foreach ($this->names as $idx => $node) { + if ($idx) { + $compiler->raw(', '); + } + + $compiler + ->raw('$context[') + ->string($node->getName()) + ->raw(']') + ; + } + $compiler->raw(')'); + } else { + if ($this->capture) { + $compiler + ->write("ob_start();\n") + ->subcompile($this->values) + ; + } + + $compiler + ->write('$context[') + ->string($this->names->getName()) + ->raw(']') + ; + + if ($this->capture) { + $compiler->raw(" = ob_get_clean()"); + } + } + + if (!$this->capture) { + $compiler->raw(' = '); + + if ($this->isMultitarget) { + $compiler->write('array('); + foreach ($this->values as $idx => $value) { + if ($idx) { + $compiler->raw(', '); + } + + $compiler->subcompile($value); + } + $compiler->raw(')'); + } else { + $compiler->subcompile($this->values); + } } - $compiler->raw(')'); - } - else - { - $compiler->subcompile($this->values); - } - } - $compiler->raw(";\n"); - } + $compiler->raw(";\n"); + } - public function getNames() - { - return $this->names; - } + public function getNames() + { + return $this->names; + } } diff --git a/lib/Twig/Node/Text.php b/lib/Twig/Node/Text.php index 89dfc5a..8133bb9 100644 --- a/lib/Twig/Node/Text.php +++ b/lib/Twig/Node/Text.php @@ -19,31 +19,31 @@ */ class Twig_Node_Text extends Twig_Node { - protected $data; + protected $data; - public function __construct($data, $lineno) - { - parent::__construct($lineno); - $this->data = $data; - } + public function __construct($data, $lineno) + { + parent::__construct($lineno); + $this->data = $data; + } - public function __toString() - { - return get_class($this).'('.$this->data.')'; - } + public function __toString() + { + return get_class($this).'('.$this->data.')'; + } - public function compile($compiler) - { - $compiler - ->addDebugInfo($this) - ->write('echo ') - ->string($this->data) - ->raw(";\n") - ; - } + public function compile($compiler) + { + $compiler + ->addDebugInfo($this) + ->write('echo ') + ->string($this->data) + ->raw(";\n") + ; + } - public function getData() - { - return $this->data; - } + public function getData() + { + return $this->data; + } } diff --git a/lib/Twig/Node/Trans.php b/lib/Twig/Node/Trans.php index 2ebc2d0..c26ac9b 100644 --- a/lib/Twig/Node/Trans.php +++ b/lib/Twig/Node/Trans.php @@ -18,127 +18,112 @@ */ class Twig_Node_Trans extends Twig_Node { - protected $count, $body, $plural; + protected $count, $body, $plural; - public function __construct($count, Twig_NodeList $body, $plural, $lineno, $tag = null) - { - parent::__construct($lineno, $tag); - - $this->count = $count; - $this->body = $body; - $this->plural = $plural; - } - - public function __toString() - { - return get_class($this).'('.$this->body.', '.$this->count.')'; - } + public function __construct($count, Twig_NodeList $body, $plural, $lineno, $tag = null) + { + parent::__construct($lineno, $tag); - public function compile($compiler) - { - $compiler->addDebugInfo($this); + $this->count = $count; + $this->body = $body; + $this->plural = $plural; + } - list($msg, $vars) = $this->compileString($this->body); + public function __toString() + { + return get_class($this).'('.$this->body.', '.$this->count.')'; + } - if (false !== $this->plural) + public function compile($compiler) { - list($msg1, $vars1) = $this->compileString($this->plural); + $compiler->addDebugInfo($this); - $vars = array_merge($vars, $vars1); - } + list($msg, $vars) = $this->compileString($this->body); - $function = false === $this->plural ? 'gettext' : 'ngettext'; + if (false !== $this->plural) { + list($msg1, $vars1) = $this->compileString($this->plural); - if ($vars) - { - $compiler - ->write('echo strtr('.$function.'(') - ->string($msg) - ; - - if (false !== $this->plural) - { - $compiler - ->raw(', ') - ->string($msg1) - ->raw(', abs(') - ->subcompile($this->count) - ->raw(')') - ; - } - - $compiler->raw('), array('); - - foreach ($vars as $var) - { - if ('count' === $var->getName()) - { - $compiler - ->string('%count%') - ->raw(' => abs(') - ->subcompile($this->count) - ->raw('), ') - ; + $vars = array_merge($vars, $vars1); } - else - { - $compiler - ->string('%'.$var->getName().'%') - ->raw(' => ') - ->subcompile($var) - ->raw(', ') - ; + + $function = false === $this->plural ? 'gettext' : 'ngettext'; + + if ($vars) { + $compiler + ->write('echo strtr('.$function.'(') + ->string($msg) + ; + + if (false !== $this->plural) { + $compiler + ->raw(', ') + ->string($msg1) + ->raw(', abs(') + ->subcompile($this->count) + ->raw(')') + ; + } + + $compiler->raw('), array('); + + foreach ($vars as $var) { + if ('count' === $var->getName()) { + $compiler + ->string('%count%') + ->raw(' => abs(') + ->subcompile($this->count) + ->raw('), ') + ; + } else { + $compiler + ->string('%'.$var->getName().'%') + ->raw(' => ') + ->subcompile($var) + ->raw(', ') + ; + } + } + + $compiler->raw("));\n"); + } else { + $compiler + ->write('echo '.$function.'(') + ->string($msg) + ->raw(");\n") + ; } - } + } - $compiler->raw("));\n"); + public function getBody() + { + return $this->body; } - else + + public function getPlural() { - $compiler - ->write('echo '.$function.'(') - ->string($msg) - ->raw(");\n") - ; + return $this->plural; } - } - - public function getBody() - { - return $this->body; - } - - public function getPlural() - { - return $this->plural; - } - - public function getCount() - { - return $this->count; - } - - protected function compileString(Twig_NodeList $body) - { - $msg = ''; - $vars = array(); - foreach ($body->getNodes() as $i => $node) + + public function getCount() { - if ($node instanceof Twig_Node_Text) - { - $msg .= $node->getData(); - } - elseif ($node instanceof Twig_Node_Print && $node->getExpression() instanceof Twig_Node_Expression_Name) - { - $msg .= sprintf('%%%s%%', $node->getExpression()->getName()); - $vars[] = $node->getExpression(); - } - else - { - throw new Twig_SyntaxError(sprintf('The text to be translated with "trans" can only contain references to simple variable'), $this->lineno); - } + return $this->count; } - return array(trim($msg), $vars); - } + protected function compileString(Twig_NodeList $body) + { + $msg = ''; + $vars = array(); + foreach ($body->getNodes() as $i => $node) { + if ($node instanceof Twig_Node_Text) { + $msg .= $node->getData(); + } elseif ($node instanceof Twig_Node_Print && $node->getExpression() instanceof Twig_Node_Expression_Name) { + $msg .= sprintf('%%%s%%', $node->getExpression()->getName()); + $vars[] = $node->getExpression(); + } else { + throw new Twig_SyntaxError(sprintf('The text to be translated with "trans" can only contain references to simple variable'), $this->lineno); + } + } + + return array(trim($msg), $vars); + } } diff --git a/lib/Twig/NodeList.php b/lib/Twig/NodeList.php index 79c5fbc..4f6dec5 100644 --- a/lib/Twig/NodeList.php +++ b/lib/Twig/NodeList.php @@ -19,44 +19,41 @@ */ class Twig_NodeList extends Twig_Node implements Twig_NodeListInterface { - protected $nodes; + protected $nodes; - public function __construct(array $nodes, $lineno = 0) - { - parent::__construct($lineno); + public function __construct(array $nodes, $lineno = 0) + { + parent::__construct($lineno); - $this->nodes = $nodes; - } + $this->nodes = $nodes; + } - public function __toString() - { - $repr = array(get_class($this).'('); - foreach ($this->nodes as $node) + public function __toString() { - foreach (explode("\n", $node->__toString()) as $line) - { - $repr[] = ' '.$line; - } + $repr = array(get_class($this).'('); + foreach ($this->nodes as $node) { + foreach (explode("\n", $node->__toString()) as $line) { + $repr[] = ' '.$line; + } + } + + return implode("\n", $repr); } - return implode("\n", $repr); - } - - public function compile($compiler) - { - foreach ($this->nodes as $node) + public function compile($compiler) { - $node->compile($compiler); + foreach ($this->nodes as $node) { + $node->compile($compiler); + } } - } - public function getNodes() - { - return $this->nodes; - } + public function getNodes() + { + return $this->nodes; + } - public function setNodes(array $nodes) - { - $this->nodes = $nodes; - } + public function setNodes(array $nodes) + { + $this->nodes = $nodes; + } } diff --git a/lib/Twig/NodeListInterface.php b/lib/Twig/NodeListInterface.php index 43df815..fe3cccd 100644 --- a/lib/Twig/NodeListInterface.php +++ b/lib/Twig/NodeListInterface.php @@ -18,13 +18,13 @@ */ interface Twig_NodeListInterface { - /** - * Returns an array of embedded nodes - */ - public function getNodes(); + /** + * Returns an array of embedded nodes + */ + public function getNodes(); - /** - * Sets the array of embedded nodes - */ - public function setNodes(array $nodes); + /** + * Sets the array of embedded nodes + */ + public function setNodes(array $nodes); } diff --git a/lib/Twig/NodeTraverser.php b/lib/Twig/NodeTraverser.php index a781504..bde3d4b 100644 --- a/lib/Twig/NodeTraverser.php +++ b/lib/Twig/NodeTraverser.php @@ -10,30 +10,27 @@ */ class Twig_NodeTraverser { - protected $env; + protected $env; - public function __construct(Twig_Environment $env) - { - $this->env = $env; - } - - public function traverse(Twig_Node $node, Twig_NodeVisitorInterface $visitor) - { - $node = $visitor->enterNode($node, $this->env); + public function __construct(Twig_Environment $env) + { + $this->env = $env; + } - if ($node instanceof Twig_NodeListInterface) + public function traverse(Twig_Node $node, Twig_NodeVisitorInterface $visitor) { - $newNodes = array(); - foreach ($nodes = $node->getNodes() as $k => $n) - { - if (null !== $n = $this->traverse($n, $visitor)) - { - $newNodes[$k] = $n; + $node = $visitor->enterNode($node, $this->env); + + if ($node instanceof Twig_NodeListInterface) { + $newNodes = array(); + foreach ($nodes = $node->getNodes() as $k => $n) { + if (null !== $n = $this->traverse($n, $visitor)) { + $newNodes[$k] = $n; + } + } + $node->setNodes($newNodes); } - } - $node->setNodes($newNodes); - } - return $visitor->leaveNode($node, $this->env); - } + return $visitor->leaveNode($node, $this->env); + } } diff --git a/lib/Twig/NodeVisitor/Escaper.php b/lib/Twig/NodeVisitor/Escaper.php index 1859dcb..4dc7559 100644 --- a/lib/Twig/NodeVisitor/Escaper.php +++ b/lib/Twig/NodeVisitor/Escaper.php @@ -10,120 +10,95 @@ */ class Twig_NodeVisitor_Escaper implements Twig_NodeVisitorInterface { - protected $statusStack = array(); - protected $blocks = array(); + protected $statusStack = array(); + protected $blocks = array(); - public function enterNode(Twig_Node $node, Twig_Environment $env) - { - if ($node instanceof Twig_Node_AutoEscape) + public function enterNode(Twig_Node $node, Twig_Environment $env) { - $this->statusStack[] = $node->getValue(); - } - elseif ($node instanceof Twig_Node_Print) - { - return $this->escapeNode($node, $env, $this->needEscaping($env)); - } - elseif ($node instanceof Twig_Node_Block) - { - $this->statusStack[] = isset($this->blocks[$node->getName()]) ? $this->blocks[$node->getName()] : $this->needEscaping($env); - } - - return $node; - } + if ($node instanceof Twig_Node_AutoEscape) { + $this->statusStack[] = $node->getValue(); + } elseif ($node instanceof Twig_Node_Print) { + return $this->escapeNode($node, $env, $this->needEscaping($env)); + } elseif ($node instanceof Twig_Node_Block) { + $this->statusStack[] = isset($this->blocks[$node->getName()]) ? $this->blocks[$node->getName()] : $this->needEscaping($env); + } - public function leaveNode(Twig_Node $node, Twig_Environment $env) - { - if ($node instanceof Twig_Node_AutoEscape || $node instanceof Twig_Node_Block) - { - array_pop($this->statusStack); + return $node; } - elseif ($node instanceof Twig_Node_BlockReference) + + public function leaveNode(Twig_Node $node, Twig_Environment $env) { - $this->blocks[$node->getName()] = $this->needEscaping($env); - } + if ($node instanceof Twig_Node_AutoEscape || $node instanceof Twig_Node_Block) { + array_pop($this->statusStack); + } elseif ($node instanceof Twig_Node_BlockReference) { + $this->blocks[$node->getName()] = $this->needEscaping($env); + } - return $node; - } + return $node; + } - protected function escapeNode(Twig_Node $node, Twig_Environment $env, $type) - { - if (false === $type) + protected function escapeNode(Twig_Node $node, Twig_Environment $env, $type) { - return $node; - } + if (false === $type) { + return $node; + } - $expression = $node instanceof Twig_Node_Print ? $node->getExpression() : $node; + $expression = $node instanceof Twig_Node_Print ? $node->getExpression() : $node; - if ($expression instanceof Twig_Node_Expression_Filter) - { - // don't escape if the primary node of the filter is not a variable - $nodes = $expression->getNodes(); - if (!$nodes[0] instanceof Twig_Node_Expression_Name) - { - return $node; - } + if ($expression instanceof Twig_Node_Expression_Filter) { + // don't escape if the primary node of the filter is not a variable + $nodes = $expression->getNodes(); + if (!$nodes[0] instanceof Twig_Node_Expression_Name) { + return $node; + } - // don't escape if there is already an "escaper" in the filter chain - $filterMap = $env->getFilters(); - foreach ($expression->getFilters() as $filter) - { - if (isset($filterMap[$filter[0]]) && $filterMap[$filter[0]]->isEscaper()) - { - return $node; + // don't escape if there is already an "escaper" in the filter chain + $filterMap = $env->getFilters(); + foreach ($expression->getFilters() as $filter) { + if (isset($filterMap[$filter[0]]) && $filterMap[$filter[0]]->isEscaper()) { + return $node; + } + } + } elseif (!$expression instanceof Twig_Node_Expression_GetAttr && !$expression instanceof Twig_Node_Expression_Name) { + // don't escape if the node is not a variable + return $node; } - } - } - elseif (!$expression instanceof Twig_Node_Expression_GetAttr && !$expression instanceof Twig_Node_Expression_Name) - { - // don't escape if the node is not a variable - return $node; - } - // escape - if ($expression instanceof Twig_Node_Expression_Filter) - { - // escape all variables in filters arguments - $filters = $expression->getFilters(); - foreach ($filters as $i => $filter) - { - foreach ($filter[1] as $j => $argument) - { - $filters[$i][1][$j] = $this->escapeNode($argument, $env, $type); - } - } + // escape + if ($expression instanceof Twig_Node_Expression_Filter) { + // escape all variables in filters arguments + $filters = $expression->getFilters(); + foreach ($filters as $i => $filter) { + foreach ($filter[1] as $j => $argument) { + $filters[$i][1][$j] = $this->escapeNode($argument, $env, $type); + } + } - $expression->setFilters($filters); - $expression->prependFilter($this->getEscaperFilter($type)); + $expression->setFilters($filters); + $expression->prependFilter($this->getEscaperFilter($type)); - return $node; - } - elseif ($node instanceof Twig_Node_Print) - { - return new Twig_Node_Print( - new Twig_Node_Expression_Filter($expression, array($this->getEscaperFilter($type)), $node->getLine()) - , $node->getLine() - ); - } - else - { - return new Twig_Node_Expression_Filter($node, array($this->getEscaperFilter($type)), $node->getLine()); + return $node; + } elseif ($node instanceof Twig_Node_Print) { + return new Twig_Node_Print( + new Twig_Node_Expression_Filter($expression, array($this->getEscaperFilter($type)), $node->getLine()) + , $node->getLine() + ); + } else { + return new Twig_Node_Expression_Filter($node, array($this->getEscaperFilter($type)), $node->getLine()); + } } - } - protected function needEscaping(Twig_Environment $env) - { - if (count($this->statusStack)) + protected function needEscaping(Twig_Environment $env) { - return $this->statusStack[count($this->statusStack) - 1]; + if (count($this->statusStack)) { + return $this->statusStack[count($this->statusStack) - 1]; + } else { + return $env->hasExtension('escaper') ? $env->getExtension('escaper')->isGlobal() : false; + } } - else + + protected function getEscaperFilter($type) { - return $env->hasExtension('escaper') ? $env->getExtension('escaper')->isGlobal() : false; + return array('escape', array(new Twig_Node_Expression_Constant((string) $type, -1))); } - } - - protected function getEscaperFilter($type) - { - return array('escape', array(new Twig_Node_Expression_Constant((string) $type, -1))); - } } diff --git a/lib/Twig/NodeVisitor/Filter.php b/lib/Twig/NodeVisitor/Filter.php index 02a27eb..bd5006d 100644 --- a/lib/Twig/NodeVisitor/Filter.php +++ b/lib/Twig/NodeVisitor/Filter.php @@ -10,66 +10,55 @@ */ class Twig_NodeVisitor_Filter implements Twig_NodeVisitorInterface { - protected $statusStack = array(); + protected $statusStack = array(); - public function enterNode(Twig_Node $node, Twig_Environment $env) - { - if ($node instanceof Twig_Node_Filter) + public function enterNode(Twig_Node $node, Twig_Environment $env) { - $this->statusStack[] = $node->getFilters(); - } - elseif ($node instanceof Twig_Node_Print || $node instanceof Twig_Node_Text) - { - return $this->applyFilters($node); - } - - return $node; - } + if ($node instanceof Twig_Node_Filter) { + $this->statusStack[] = $node->getFilters(); + } elseif ($node instanceof Twig_Node_Print || $node instanceof Twig_Node_Text) { + return $this->applyFilters($node); + } - public function leaveNode(Twig_Node $node, Twig_Environment $env) - { - if ($node instanceof Twig_Node_Filter) - { - array_pop($this->statusStack); + return $node; } - return $node; - } - - protected function applyFilters(Twig_Node $node) - { - if (false === $filters = $this->getCurrentFilters()) + public function leaveNode(Twig_Node $node, Twig_Environment $env) { - return $node; - } + if ($node instanceof Twig_Node_Filter) { + array_pop($this->statusStack); + } - if ($node instanceof Twig_Node_Text) - { - $expression = new Twig_Node_Expression_Constant($node->getData(), $node->getLine()); - } - else - { - $expression = $node->getExpression(); + return $node; } - // filters - if ($expression instanceof Twig_Node_Expression_Filter) + protected function applyFilters(Twig_Node $node) { - $expression->appendFilters($filters); + if (false === $filters = $this->getCurrentFilters()) { + return $node; + } + + if ($node instanceof Twig_Node_Text) { + $expression = new Twig_Node_Expression_Constant($node->getData(), $node->getLine()); + } else { + $expression = $node->getExpression(); + } - return $node; + // filters + if ($expression instanceof Twig_Node_Expression_Filter) { + $expression->appendFilters($filters); + + return $node; + } else { + return new Twig_Node_Print( + new Twig_Node_Expression_Filter($expression, $filters, $node->getLine()) + , $node->getLine() + ); + } } - else + + protected function getCurrentFilters() { - return new Twig_Node_Print( - new Twig_Node_Expression_Filter($expression, $filters, $node->getLine()) - , $node->getLine() - ); + return count($this->statusStack) ? $this->statusStack[count($this->statusStack) - 1] : false; } - } - - protected function getCurrentFilters() - { - return count($this->statusStack) ? $this->statusStack[count($this->statusStack) - 1] : false; - } } diff --git a/lib/Twig/NodeVisitor/Sandbox.php b/lib/Twig/NodeVisitor/Sandbox.php index 3739376..197a4e7 100644 --- a/lib/Twig/NodeVisitor/Sandbox.php +++ b/lib/Twig/NodeVisitor/Sandbox.php @@ -10,50 +10,43 @@ */ class Twig_NodeVisitor_Sandbox implements Twig_NodeVisitorInterface { - protected $inAModule = false; - protected $tags; - protected $filters; + protected $inAModule = false; + protected $tags; + protected $filters; - public function enterNode(Twig_Node $node, Twig_Environment $env) - { - if ($node instanceof Twig_Node_Module) + public function enterNode(Twig_Node $node, Twig_Environment $env) { - $this->inAModule = true; - $this->tags = array(); - $this->filters = array(); + if ($node instanceof Twig_Node_Module) { + $this->inAModule = true; + $this->tags = array(); + $this->filters = array(); - return $node; - } - elseif ($this->inAModule) - { - // look for tags - if ($node->getTag()) - { - $this->tags[$node->getTag()] = true; - } + return $node; + } elseif ($this->inAModule) { + // look for tags + if ($node->getTag()) { + $this->tags[$node->getTag()] = true; + } - // look for filters - if ($node instanceof Twig_Node_Expression_Filter) - { - foreach ($node->getFilters() as $filter) - { - $this->filters[$filter[0]] = true; + // look for filters + if ($node instanceof Twig_Node_Expression_Filter) { + foreach ($node->getFilters() as $filter) { + $this->filters[$filter[0]] = true; + } + } } - } - } - return $node; - } + return $node; + } - public function leaveNode(Twig_Node $node, Twig_Environment $env) - { - if ($node instanceof Twig_Node_Module) + public function leaveNode(Twig_Node $node, Twig_Environment $env) { - $node->setUsedFilters(array_keys($this->filters)); - $node->setUsedTags(array_keys($this->tags)); - $this->inAModule = false; - } + if ($node instanceof Twig_Node_Module) { + $node->setUsedFilters(array_keys($this->filters)); + $node->setUsedTags(array_keys($this->tags)); + $this->inAModule = false; + } - return $node; - } + return $node; + } } diff --git a/lib/Twig/NodeVisitorInterface.php b/lib/Twig/NodeVisitorInterface.php index 2d2277b..d3c2f2f 100644 --- a/lib/Twig/NodeVisitorInterface.php +++ b/lib/Twig/NodeVisitorInterface.php @@ -2,7 +2,7 @@ interface Twig_NodeVisitorInterface { - public function enterNode(Twig_Node $node, Twig_Environment $env); + public function enterNode(Twig_Node $node, Twig_Environment $env); - public function leaveNode(Twig_Node $node, Twig_Environment $env); + public function leaveNode(Twig_Node $node, Twig_Environment $env); } diff --git a/lib/Twig/Parser.php b/lib/Twig/Parser.php index 03a7621..a0dc62e 100644 --- a/lib/Twig/Parser.php +++ b/lib/Twig/Parser.php @@ -11,227 +11,211 @@ */ class Twig_Parser { - protected $stream; - protected $extends; - protected $handlers; - protected $visitors; - protected $expressionParser; - protected $blocks; - protected $blockStack; - protected $macros; - protected $env; + protected $stream; + protected $extends; + protected $handlers; + protected $visitors; + protected $expressionParser; + protected $blocks; + protected $blockStack; + protected $macros; + protected $env; + + public function __construct(Twig_Environment $env = null) + { + $this->setEnvironment($env); + } + + public function setEnvironment(Twig_Environment $env) + { + $this->env = $env; + + $this->handlers = array(); + $this->visitors = array(); - public function __construct(Twig_Environment $env = null) - { - $this->setEnvironment($env); - } + // tag handlers + foreach ($this->env->getTokenParsers() as $handler) { + $handler->setParser($this); - public function setEnvironment(Twig_Environment $env) - { - $this->env = $env; + $this->handlers[$handler->getTag()] = $handler; + } - $this->handlers = array(); - $this->visitors = array(); + // node visitors + $this->visitors = $env->getNodeVisitors(); + } - // tag handlers - foreach ($this->env->getTokenParsers() as $handler) + /** + * Converts a token stream to a node tree. + * + * @param Twig_TokenStream $stream A token stream instance + * + * @return Twig_Node_Module A node tree + */ + public function parse(Twig_TokenStream $stream) { - $handler->setParser($this); + if (null === $this->expressionParser) { + $this->expressionParser = new Twig_ExpressionParser($this); + } + + $this->stream = $stream; + $this->extends = null; + $this->blocks = array(); + $this->macros = array(); + $this->blockStack = array(); + + try { + $body = $this->subparse(null); + } catch (Twig_SyntaxError $e) { + if (is_null($e->getFilename())) { + $e->setFilename($this->stream->getFilename()); + } + + throw $e; + } + + if (!is_null($this->extends)) { + foreach ($this->blocks as $block) { + $block->setParent($this->extends); + } + } - $this->handlers[$handler->getTag()] = $handler; + $node = new Twig_Node_Module($body, $this->extends, $this->blocks, $this->macros, $this->stream->getFilename()); + + $t = new Twig_NodeTraverser($this->env); + foreach ($this->visitors as $visitor) { + $node = $t->traverse($node, $visitor); + } + + return $node; } - // node visitors - $this->visitors = $env->getNodeVisitors(); - } + public function subparse($test, $drop_needle = false) + { + $lineno = $this->getCurrentToken()->getLine(); + $rv = array(); + while (!$this->stream->isEOF()) { + switch ($this->getCurrentToken()->getType()) { + case Twig_Token::TEXT_TYPE: + $token = $this->stream->next(); + $rv[] = new Twig_Node_Text($token->getValue(), $token->getLine()); + break; + + case Twig_Token::VAR_START_TYPE: + $token = $this->stream->next(); + $expr = $this->expressionParser->parseExpression(); + $this->stream->expect(Twig_Token::VAR_END_TYPE); + $rv[] = new Twig_Node_Print($expr, $token->getLine()); + break; + + case Twig_Token::BLOCK_START_TYPE: + $this->stream->next(); + $token = $this->getCurrentToken(); + + if ($token->getType() !== Twig_Token::NAME_TYPE) { + throw new Twig_SyntaxError('A block must start with a tag name', $token->getLine()); + } + + if (!is_null($test) && call_user_func($test, $token)) { + if ($drop_needle) { + $this->stream->next(); + } + + return new Twig_NodeList($rv, $lineno); + } + + if (!isset($this->handlers[$token->getValue()])) { + throw new Twig_SyntaxError(sprintf('Unknown tag name "%s"', $token->getValue()), $token->getLine()); + } + + $this->stream->next(); + + $subparser = $this->handlers[$token->getValue()]; + $node = $subparser->parse($token); + if (!is_null($node)) { + $rv[] = $node; + } + break; + + default: + throw new LogicException('Lexer or parser ended up in unsupported state.'); + } + } - /** - * Converts a token stream to a node tree. - * - * @param Twig_TokenStream $stream A token stream instance - * - * @return Twig_Node_Module A node tree - */ - public function parse(Twig_TokenStream $stream) - { - if (null === $this->expressionParser) + return new Twig_NodeList($rv, $lineno); + } + + public function addHandler($name, $class) { - $this->expressionParser = new Twig_ExpressionParser($this); + $this->handlers[$name] = $class; } - $this->stream = $stream; - $this->extends = null; - $this->blocks = array(); - $this->macros = array(); - $this->blockStack = array(); + public function addNodeVisitor(Twig_NodeVisitorInterface $visitor) + { + $this->visitors[] = $visitor; + } - try + public function getBlockStack() { - $body = $this->subparse(null); + return $this->blockStack; } - catch (Twig_SyntaxError $e) + + public function peekBlockStack() { - if (is_null($e->getFilename())) - { - $e->setFilename($this->stream->getFilename()); - } + return $this->blockStack[count($this->blockStack) - 1]; + } - throw $e; + public function popBlockStack() + { + array_pop($this->blockStack); } - if (!is_null($this->extends)) + public function pushBlockStack($name) { - foreach ($this->blocks as $block) - { - $block->setParent($this->extends); - } + $this->blockStack[] = $name; } - $node = new Twig_Node_Module($body, $this->extends, $this->blocks, $this->macros, $this->stream->getFilename()); + public function hasBlock($name) + { + return isset($this->blocks[$name]); + } - $t = new Twig_NodeTraverser($this->env); - foreach ($this->visitors as $visitor) + public function setBlock($name, $value) { - $node = $t->traverse($node, $visitor); + $this->blocks[$name] = $value; } - return $node; - } + public function hasMacro($name) + { + return isset($this->macros[$name]); + } - public function subparse($test, $drop_needle = false) - { - $lineno = $this->getCurrentToken()->getLine(); - $rv = array(); - while (!$this->stream->isEOF()) + public function setMacro($name, $value) { - switch ($this->getCurrentToken()->getType()) - { - case Twig_Token::TEXT_TYPE: - $token = $this->stream->next(); - $rv[] = new Twig_Node_Text($token->getValue(), $token->getLine()); - break; + $this->macros[$name] = $value; + } - case Twig_Token::VAR_START_TYPE: - $token = $this->stream->next(); - $expr = $this->expressionParser->parseExpression(); - $this->stream->expect(Twig_Token::VAR_END_TYPE); - $rv[] = new Twig_Node_Print($expr, $token->getLine()); - break; + public function getExpressionParser() + { + return $this->expressionParser; + } - case Twig_Token::BLOCK_START_TYPE: - $this->stream->next(); - $token = $this->getCurrentToken(); + public function getParent() + { + return $this->extends; + } - if ($token->getType() !== Twig_Token::NAME_TYPE) - { - throw new Twig_SyntaxError('A block must start with a tag name', $token->getLine()); - } + public function setParent($extends) + { + $this->extends = $extends; + } - if (!is_null($test) && call_user_func($test, $token)) - { - if ($drop_needle) - { - $this->stream->next(); - } + public function getStream() + { + return $this->stream; + } - return new Twig_NodeList($rv, $lineno); - } - - if (!isset($this->handlers[$token->getValue()])) - { - throw new Twig_SyntaxError(sprintf('Unknown tag name "%s"', $token->getValue()), $token->getLine()); - } - - $this->stream->next(); - - $subparser = $this->handlers[$token->getValue()]; - $node = $subparser->parse($token); - if (!is_null($node)) - { - $rv[] = $node; - } - break; - - default: - throw new LogicException('Lexer or parser ended up in unsupported state.'); - } - } - - return new Twig_NodeList($rv, $lineno); - } - - public function addHandler($name, $class) - { - $this->handlers[$name] = $class; - } - - public function addNodeVisitor(Twig_NodeVisitorInterface $visitor) - { - $this->visitors[] = $visitor; - } - - public function getBlockStack() - { - return $this->blockStack; - } - - public function peekBlockStack() - { - return $this->blockStack[count($this->blockStack) - 1]; - } - - public function popBlockStack() - { - array_pop($this->blockStack); - } - - public function pushBlockStack($name) - { - $this->blockStack[] = $name; - } - - public function hasBlock($name) - { - return isset($this->blocks[$name]); - } - - public function setBlock($name, $value) - { - $this->blocks[$name] = $value; - } - - public function hasMacro($name) - { - return isset($this->macros[$name]); - } - - public function setMacro($name, $value) - { - $this->macros[$name] = $value; - } - - public function getExpressionParser() - { - return $this->expressionParser; - } - - public function getParent() - { - return $this->extends; - } - - public function setParent($extends) - { - $this->extends = $extends; - } - - public function getStream() - { - return $this->stream; - } - - public function getCurrentToken() - { - return $this->stream->getCurrent(); - } + public function getCurrentToken() + { + return $this->stream->getCurrent(); + } } diff --git a/lib/Twig/ParserInterface.php b/lib/Twig/ParserInterface.php index 34156e8..1bbcd50 100644 --- a/lib/Twig/ParserInterface.php +++ b/lib/Twig/ParserInterface.php @@ -18,12 +18,12 @@ */ interface Twig_ParserInterface { - /** - * Converts a token stream to a node tree. - * - * @param Twig_TokenStream $stream A token stream instance - * - * @return Twig_Node_Module A node tree - */ - public function parser(Twig_TokenStream $code); + /** + * Converts a token stream to a node tree. + * + * @param Twig_TokenStream $stream A token stream instance + * + * @return Twig_Node_Module A node tree + */ + public function parser(Twig_TokenStream $code); } diff --git a/lib/Twig/Resource.php b/lib/Twig/Resource.php index 37058ad..f1274c7 100644 --- a/lib/Twig/Resource.php +++ b/lib/Twig/Resource.php @@ -10,84 +10,70 @@ */ abstract class Twig_Resource { - protected $env; - protected $cache; + protected $env; + protected $cache; - public function __construct(Twig_Environment $env) - { - $this->env = $env; - $this->cache = array(); - } - - public function getEnvironment() - { - return $this->env; - } - - protected function resolveMissingFilter($name) - { - throw new Twig_RuntimeError(sprintf('The filter "%s" does not exist', $name)); - } - - protected function getAttribute($object, $item, array $arguments = array(), $arrayOnly = false) - { - $item = (string) $item; + public function __construct(Twig_Environment $env) + { + $this->env = $env; + $this->cache = array(); + } - if ((is_array($object) || is_object($object) && $object instanceof ArrayAccess) && isset($object[$item])) + public function getEnvironment() { - return $object[$item]; + return $this->env; } - if ($arrayOnly || !is_object($object)) + protected function resolveMissingFilter($name) { - return null; + throw new Twig_RuntimeError(sprintf('The filter "%s" does not exist', $name)); } - if (isset($object->$item)) + protected function getAttribute($object, $item, array $arguments = array(), $arrayOnly = false) { - if ($this->env->hasExtension('sandbox')) - { - $this->env->getExtension('sandbox')->checkPropertyAllowed($object, $item); - } + $item = (string) $item; - return $object->$item; - } + if ((is_array($object) || is_object($object) && $object instanceof ArrayAccess) && isset($object[$item])) { + return $object[$item]; + } - $class = get_class($object); + if ($arrayOnly || !is_object($object)) { + return null; + } - if (!isset($this->cache[$class])) - { - $r = new ReflectionClass($class); - $this->cache[$class] = array(); - foreach ($r->getMethods(ReflectionMethod::IS_STATIC | ReflectionMethod::IS_PUBLIC | ReflectionMethod::IS_FINAL) as $method) - { - $this->cache[$class][strtolower($method->getName())] = true; - } - } + if (isset($object->$item)) { + if ($this->env->hasExtension('sandbox')) { + $this->env->getExtension('sandbox')->checkPropertyAllowed($object, $item); + } - $item = strtolower($item); - if (isset($this->cache[$class][$item])) - { - $method = $item; - } - elseif (isset($this->cache[$class]['get'.$item])) - { - $method = 'get'.$item; - } - elseif (isset($this->cache[$class]['__call'])) - { - $method = $item; - } - else - { - return null; - } + return $object->$item; + } - if ($this->env->hasExtension('sandbox')) - { - $this->env->getExtension('sandbox')->checkMethodAllowed($object, $method); - } + $class = get_class($object); + + if (!isset($this->cache[$class])) { + $r = new ReflectionClass($class); + $this->cache[$class] = array(); + foreach ($r->getMethods(ReflectionMethod::IS_STATIC | ReflectionMethod::IS_PUBLIC | ReflectionMethod::IS_FINAL) as $method) { + $this->cache[$class][strtolower($method->getName())] = true; + } + } + + $item = strtolower($item); + if (isset($this->cache[$class][$item])) { + $method = $item; + } elseif (isset($this->cache[$class]['get'.$item])) { + $method = 'get'.$item; + } elseif (isset($this->cache[$class]['__call'])) { + $method = $item; + } else { + return null; + } - return call_user_func_array(array($object, $method), $arguments); - } + if ($this->env->hasExtension('sandbox')) { + $this->env->getExtension('sandbox')->checkMethodAllowed($object, $method); + } + + return call_user_func_array(array($object, $method), $arguments); + } } diff --git a/lib/Twig/Sandbox/SecurityPolicy.php b/lib/Twig/Sandbox/SecurityPolicy.php index fe6ac1d..04dae6e 100644 --- a/lib/Twig/Sandbox/SecurityPolicy.php +++ b/lib/Twig/Sandbox/SecurityPolicy.php @@ -18,93 +18,83 @@ */ class Twig_Sandbox_SecurityPolicy implements Twig_Sandbox_SecurityPolicyInterface { - protected $allowedTags; - protected $allowedFilters; - protected $allowedMethods; - protected $allowedProperties; + protected $allowedTags; + protected $allowedFilters; + protected $allowedMethods; + protected $allowedProperties; - public function __construct(array $allowedTags = array(), array $allowedFilters = array(), array $allowedMethods = array(), array $allowedProperties = array()) - { - $this->allowedTags = $allowedTags; - $this->allowedFilters = $allowedFilters; - $this->allowedMethods = $allowedMethods; - $this->allowedProperties = $allowedProperties; - } - - public function setAllowedTags(array $tags) - { - $this->allowedTags = $tags; - } - - public function setAllowedFilters(array $filters) - { - $this->allowedFilters = $filters; - } - - public function setAllowedMethods(array $methods) - { - $this->allowedMethods = $methods; - } - - public function setAllowedProperties(array $properties) - { - $this->allowedProperties = $properties; - } + public function __construct(array $allowedTags = array(), array $allowedFilters = array(), array $allowedMethods = array(), array $allowedProperties = array()) + { + $this->allowedTags = $allowedTags; + $this->allowedFilters = $allowedFilters; + $this->allowedMethods = $allowedMethods; + $this->allowedProperties = $allowedProperties; + } - public function checkSecurity($tags, $filters) - { - foreach ($tags as $tag) + public function setAllowedTags(array $tags) { - if (!in_array($tag, $this->allowedTags)) - { - throw new Twig_Sandbox_SecurityError(sprintf('Tag "%s" is not allowed.', $tag)); - } + $this->allowedTags = $tags; } - foreach ($filters as $filter) + public function setAllowedFilters(array $filters) { - if (!in_array($filter, $this->allowedFilters)) - { - throw new Twig_Sandbox_SecurityError(sprintf('Filter "%s" is not allowed.', $filter)); - } + $this->allowedFilters = $filters; } - } - public function checkMethodAllowed($obj, $method) - { - $allowed = false; - foreach ($this->allowedMethods as $class => $methods) + public function setAllowedMethods(array $methods) { - if ($obj instanceof $class) - { - $allowed = in_array($method, is_array($methods) ? $methods : array($methods)); + $this->allowedMethods = $methods; + } - break; - } + public function setAllowedProperties(array $properties) + { + $this->allowedProperties = $properties; } - if (!$allowed) + public function checkSecurity($tags, $filters) { - throw new Twig_Sandbox_SecurityError(sprintf('Calling "%s" method on a "%s" object is not allowed.', $method, get_class($obj))); + foreach ($tags as $tag) { + if (!in_array($tag, $this->allowedTags)) { + throw new Twig_Sandbox_SecurityError(sprintf('Tag "%s" is not allowed.', $tag)); + } + } + + foreach ($filters as $filter) { + if (!in_array($filter, $this->allowedFilters)) { + throw new Twig_Sandbox_SecurityError(sprintf('Filter "%s" is not allowed.', $filter)); + } + } } - } - public function checkPropertyAllowed($obj, $property) - { - $allowed = false; - foreach ($this->allowedProperties as $class => $properties) + public function checkMethodAllowed($obj, $method) { - if ($obj instanceof $class) - { - $allowed = in_array($property, is_array($properties) ? $properties : array($properties)); + $allowed = false; + foreach ($this->allowedMethods as $class => $methods) { + if ($obj instanceof $class) { + $allowed = in_array($method, is_array($methods) ? $methods : array($methods)); - break; - } + break; + } + } + + if (!$allowed) { + throw new Twig_Sandbox_SecurityError(sprintf('Calling "%s" method on a "%s" object is not allowed.', $method, get_class($obj))); + } } - if (!$allowed) + public function checkPropertyAllowed($obj, $property) { - throw new Twig_Sandbox_SecurityError(sprintf('Calling "%s" property on a "%s" object is not allowed.', $property, get_class($obj))); + $allowed = false; + foreach ($this->allowedProperties as $class => $properties) { + if ($obj instanceof $class) { + $allowed = in_array($property, is_array($properties) ? $properties : array($properties)); + + break; + } + } + + if (!$allowed) { + throw new Twig_Sandbox_SecurityError(sprintf('Calling "%s" property on a "%s" object is not allowed.', $property, get_class($obj))); + } } - } } diff --git a/lib/Twig/Sandbox/SecurityPolicyInterface.php b/lib/Twig/Sandbox/SecurityPolicyInterface.php index bcb9f02..1eb50fc 100644 --- a/lib/Twig/Sandbox/SecurityPolicyInterface.php +++ b/lib/Twig/Sandbox/SecurityPolicyInterface.php @@ -18,9 +18,9 @@ */ interface Twig_Sandbox_SecurityPolicyInterface { - public function checkSecurity($tags, $filters); + public function checkSecurity($tags, $filters); - public function checkMethodAllowed($obj, $method); + public function checkMethodAllowed($obj, $method); - public function checkPropertyAllowed($obj, $method); + public function checkPropertyAllowed($obj, $method); } diff --git a/lib/Twig/SyntaxError.php b/lib/Twig/SyntaxError.php index 5fe0b66..193dce2 100644 --- a/lib/Twig/SyntaxError.php +++ b/lib/Twig/SyntaxError.php @@ -19,35 +19,35 @@ */ class Twig_SyntaxError extends Twig_Error { - protected $lineno; - protected $filename; - protected $rawMessage; + protected $lineno; + protected $filename; + protected $rawMessage; - public function __construct($message, $lineno, $filename = null) - { - $this->lineno = $lineno; - $this->filename = $filename; - $this->rawMessage = $message; + public function __construct($message, $lineno, $filename = null) + { + $this->lineno = $lineno; + $this->filename = $filename; + $this->rawMessage = $message; - $this->updateRepr(); + $this->updateRepr(); - parent::__construct($this->message, $lineno); - } + parent::__construct($this->message, $lineno); + } - public function getFilename() - { - return $this->filename; - } + public function getFilename() + { + return $this->filename; + } - public function setFilename($filename) - { - $this->filename = $filename; + public function setFilename($filename) + { + $this->filename = $filename; - $this->updateRepr(); - } + $this->updateRepr(); + } - protected function updateRepr() - { - $this->message = $this->rawMessage.' in '.($this->filename ? $this->filename : 'n/a').' at line '.$this->lineno; - } + protected function updateRepr() + { + $this->message = $this->rawMessage.' in '.($this->filename ? $this->filename : 'n/a').' at line '.$this->lineno; + } } diff --git a/lib/Twig/Template.php b/lib/Twig/Template.php index ee08910..b455151 100644 --- a/lib/Twig/Template.php +++ b/lib/Twig/Template.php @@ -11,29 +11,26 @@ */ abstract class Twig_Template extends Twig_Resource implements Twig_TemplateInterface { - /** - * Renders the template with the given context and returns it as string. - * - * @param array $context An array of parameters to pass to the template - * - * @return string The rendered template - */ - public function render(array $context) - { - ob_start(); - try + /** + * Renders the template with the given context and returns it as string. + * + * @param array $context An array of parameters to pass to the template + * + * @return string The rendered template + */ + public function render(array $context) { - $this->display($context); - } - catch (Exception $e) - { - ob_end_clean(); + ob_start(); + try { + $this->display($context); + } catch (Exception $e) { + ob_end_clean(); - throw $e; - } + throw $e; + } - return ob_get_clean(); - } + return ob_get_clean(); + } - abstract protected function getName(); + abstract protected function getName(); } diff --git a/lib/Twig/TemplateInterface.php b/lib/Twig/TemplateInterface.php index dafe5a9..0f74ffc 100644 --- a/lib/Twig/TemplateInterface.php +++ b/lib/Twig/TemplateInterface.php @@ -10,26 +10,26 @@ */ interface Twig_TemplateInterface { - /** - * Renders the template with the given context and returns it as string. - * - * @param array $context An array of parameters to pass to the template - * - * @return string The rendered template - */ - public function render(array $context); + /** + * Renders the template with the given context and returns it as string. + * + * @param array $context An array of parameters to pass to the template + * + * @return string The rendered template + */ + public function render(array $context); - /** - * Displays the template with the given context. - * - * @param array $context An array of parameters to pass to the template - */ - public function display(array $context); + /** + * Displays the template with the given context. + * + * @param array $context An array of parameters to pass to the template + */ + public function display(array $context); - /** - * Returns the bound environment for this template. - * - * @return Twig_Environment The current environment - */ - public function getEnvironment(); + /** + * Returns the bound environment for this template. + * + * @return Twig_Environment The current environment + */ + public function getEnvironment(); } diff --git a/lib/Twig/Token.php b/lib/Twig/Token.php index 235d7f6..88bf898 100644 --- a/lib/Twig/Token.php +++ b/lib/Twig/Token.php @@ -11,113 +11,111 @@ */ class Twig_Token { - protected $value; - protected $type; - protected $lineno; + protected $value; + protected $type; + protected $lineno; - const EOF_TYPE = -1; - const TEXT_TYPE = 0; - const BLOCK_START_TYPE = 1; - const VAR_START_TYPE = 2; - const BLOCK_END_TYPE = 3; - const VAR_END_TYPE = 4; - const NAME_TYPE = 5; - const NUMBER_TYPE = 6; - const STRING_TYPE = 7; - const OPERATOR_TYPE = 8; + const EOF_TYPE = -1; + const TEXT_TYPE = 0; + const BLOCK_START_TYPE = 1; + const VAR_START_TYPE = 2; + const BLOCK_END_TYPE = 3; + const VAR_END_TYPE = 4; + const NAME_TYPE = 5; + const NUMBER_TYPE = 6; + const STRING_TYPE = 7; + const OPERATOR_TYPE = 8; - public function __construct($type, $value, $lineno) - { - $this->type = $type; - $this->value = $value; - $this->lineno = $lineno; - } - - public function __toString() - { - return sprintf('%s(%s)', self::getTypeAsString($this->type, true), $this->value); - } + public function __construct($type, $value, $lineno) + { + $this->type = $type; + $this->value = $value; + $this->lineno = $lineno; + } - /** - * Test the current token for a type. The first argument is the type - * of the token (if not given Twig_Token::NAME_NAME), the second the - * value of the token (if not given value is not checked). - * the token value can be an array if multiple checks shoudl be - * performed. - */ - public function test($type, $values = null) - { - if (is_null($values) && !is_int($type)) + public function __toString() { - $values = $type; - $type = self::NAME_TYPE; + return sprintf('%s(%s)', self::getTypeAsString($this->type, true), $this->value); } - return ($this->type === $type) && ( - is_null($values) || - (is_array($values) && in_array($this->value, $values)) || - $this->value == $values - ); - } + /** + * Test the current token for a type. The first argument is the type + * of the token (if not given Twig_Token::NAME_NAME), the second the + * value of the token (if not given value is not checked). + * the token value can be an array if multiple checks shoudl be + * performed. + */ + public function test($type, $values = null) + { + if (is_null($values) && !is_int($type)) { + $values = $type; + $type = self::NAME_TYPE; + } - public function getLine() - { - return $this->lineno; - } + return ($this->type === $type) && ( + is_null($values) || + (is_array($values) && in_array($this->value, $values)) || + $this->value == $values + ); + } - public function getType() - { - return $this->type; - } + public function getLine() + { + return $this->lineno; + } - public function getValue() - { - return $this->value; - } + public function getType() + { + return $this->type; + } - public function setValue($value) - { - $this->value = $value; - } + public function getValue() + { + return $this->value; + } - static public function getTypeAsString($type, $short = false) - { - switch ($type) + public function setValue($value) { - case self::EOF_TYPE: - $name = 'EOF_TYPE'; - break; - case self::TEXT_TYPE: - $name = 'TEXT_TYPE'; - break; - case self::BLOCK_START_TYPE: - $name = 'BLOCK_START_TYPE'; - break; - case self::VAR_START_TYPE: - $name = 'VAR_START_TYPE'; - break; - case self::BLOCK_END_TYPE: - $name = 'BLOCK_END_TYPE'; - break; - case self::VAR_END_TYPE: - $name = 'VAR_END_TYPE'; - break; - case self::NAME_TYPE: - $name = 'NAME_TYPE'; - break; - case self::NUMBER_TYPE: - $name = 'NUMBER_TYPE'; - break; - case self::STRING_TYPE: - $name = 'STRING_TYPE'; - break; - case self::OPERATOR_TYPE: - $name = 'OPERATOR_TYPE'; - break; - default: - throw new InvalidArgumentException(sprintf('Token of type %s does not exist.', $type)); + $this->value = $value; } - return $short ? $name : 'Twig_Token::'.$name; - } + static public function getTypeAsString($type, $short = false) + { + switch ($type) { + case self::EOF_TYPE: + $name = 'EOF_TYPE'; + break; + case self::TEXT_TYPE: + $name = 'TEXT_TYPE'; + break; + case self::BLOCK_START_TYPE: + $name = 'BLOCK_START_TYPE'; + break; + case self::VAR_START_TYPE: + $name = 'VAR_START_TYPE'; + break; + case self::BLOCK_END_TYPE: + $name = 'BLOCK_END_TYPE'; + break; + case self::VAR_END_TYPE: + $name = 'VAR_END_TYPE'; + break; + case self::NAME_TYPE: + $name = 'NAME_TYPE'; + break; + case self::NUMBER_TYPE: + $name = 'NUMBER_TYPE'; + break; + case self::STRING_TYPE: + $name = 'STRING_TYPE'; + break; + case self::OPERATOR_TYPE: + $name = 'OPERATOR_TYPE'; + break; + default: + throw new InvalidArgumentException(sprintf('Token of type %s does not exist.', $type)); + } + + return $short ? $name : 'Twig_Token::'.$name; + } } diff --git a/lib/Twig/TokenParser.php b/lib/Twig/TokenParser.php index 9fe3dc5..6f9ff0a 100644 --- a/lib/Twig/TokenParser.php +++ b/lib/Twig/TokenParser.php @@ -11,14 +11,14 @@ */ abstract class Twig_TokenParser { - protected $parser; + protected $parser; - public function setParser(Twig_Parser $parser) - { - $this->parser = $parser; - } + public function setParser(Twig_Parser $parser) + { + $this->parser = $parser; + } - abstract public function parse(Twig_Token $token); + abstract public function parse(Twig_Token $token); - abstract public function getTag(); + abstract public function getTag(); } diff --git a/lib/Twig/TokenParser/AutoEscape.php b/lib/Twig/TokenParser/AutoEscape.php index 8943e2e..01e1b88 100644 --- a/lib/Twig/TokenParser/AutoEscape.php +++ b/lib/Twig/TokenParser/AutoEscape.php @@ -10,40 +10,37 @@ */ class Twig_TokenParser_AutoEscape extends Twig_TokenParser { - public function parse(Twig_Token $token) - { - $lineno = $token->getLine(); - $value = $this->parser->getStream()->expect(Twig_Token::NAME_TYPE)->getValue(); - if (!in_array($value, array('on', 'off'))) + public function parse(Twig_Token $token) { - throw new Twig_SyntaxError("Autoescape value must be 'on' or 'off'", $lineno); - } - $value = 'on' === $value ? true : false; + $lineno = $token->getLine(); + $value = $this->parser->getStream()->expect(Twig_Token::NAME_TYPE)->getValue(); + if (!in_array($value, array('on', 'off'))) { + throw new Twig_SyntaxError("Autoescape value must be 'on' or 'off'", $lineno); + } + $value = 'on' === $value ? true : false; - if ($this->parser->getStream()->test(Twig_Token::NAME_TYPE)) - { - if (false === $value) - { - throw new Twig_SyntaxError(sprintf('Unexpected escaping strategy as you set autoescaping to off.', $lineno), -1); - } + if ($this->parser->getStream()->test(Twig_Token::NAME_TYPE)) { + if (false === $value) { + throw new Twig_SyntaxError(sprintf('Unexpected escaping strategy as you set autoescaping to off.', $lineno), -1); + } - $value = $this->parser->getStream()->next()->getValue(); - } + $value = $this->parser->getStream()->next()->getValue(); + } - $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); - $body = $this->parser->subparse(array($this, 'decideBlockEnd'), true); - $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); + $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); + $body = $this->parser->subparse(array($this, 'decideBlockEnd'), true); + $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); - return new Twig_Node_AutoEscape($value, $body, $lineno, $this->getTag()); - } + return new Twig_Node_AutoEscape($value, $body, $lineno, $this->getTag()); + } - public function decideBlockEnd($token) - { - return $token->test('endautoescape'); - } + public function decideBlockEnd($token) + { + return $token->test('endautoescape'); + } - public function getTag() - { - return 'autoescape'; - } + public function getTag() + { + return 'autoescape'; + } } diff --git a/lib/Twig/TokenParser/Block.php b/lib/Twig/TokenParser/Block.php index ea61515..cbad921 100644 --- a/lib/Twig/TokenParser/Block.php +++ b/lib/Twig/TokenParser/Block.php @@ -11,54 +11,48 @@ */ class Twig_TokenParser_Block extends Twig_TokenParser { - public function parse(Twig_Token $token) - { - $lineno = $token->getLine(); - $stream = $this->parser->getStream(); - $name = $stream->expect(Twig_Token::NAME_TYPE)->getValue(); - if ($this->parser->hasBlock($name)) + public function parse(Twig_Token $token) { - throw new Twig_SyntaxError("The block '$name' has already been defined", $lineno); - } - $this->parser->pushBlockStack($name); - - if ($stream->test(Twig_Token::BLOCK_END_TYPE)) - { - $stream->next(); + $lineno = $token->getLine(); + $stream = $this->parser->getStream(); + $name = $stream->expect(Twig_Token::NAME_TYPE)->getValue(); + if ($this->parser->hasBlock($name)) { + throw new Twig_SyntaxError("The block '$name' has already been defined", $lineno); + } + $this->parser->pushBlockStack($name); + + if ($stream->test(Twig_Token::BLOCK_END_TYPE)) { + $stream->next(); + + $body = $this->parser->subparse(array($this, 'decideBlockEnd'), true); + if ($stream->test(Twig_Token::NAME_TYPE)) { + $value = $stream->next()->getValue(); + + if ($value != $name) { + throw new Twig_SyntaxError(sprintf("Expected endblock for block '$name' (but %s given)", $value), $lineno); + } + } + } else { + $body = new Twig_NodeList(array( + new Twig_Node_Print($this->parser->getExpressionParser()->parseExpression(), $lineno), + )); + } + $stream->expect(Twig_Token::BLOCK_END_TYPE); - $body = $this->parser->subparse(array($this, 'decideBlockEnd'), true); - if ($stream->test(Twig_Token::NAME_TYPE)) - { - $value = $stream->next()->getValue(); + $block = new Twig_Node_Block($name, $body, $lineno); + $this->parser->setBlock($name, $block); + $this->parser->popBlockStack(); - if ($value != $name) - { - throw new Twig_SyntaxError(sprintf("Expected endblock for block '$name' (but %s given)", $value), $lineno); - } - } + return new Twig_Node_BlockReference($name, $lineno, $this->getTag()); } - else + + public function decideBlockEnd($token) { - $body = new Twig_NodeList(array( - new Twig_Node_Print($this->parser->getExpressionParser()->parseExpression(), $lineno), - )); + return $token->test('endblock'); } - $stream->expect(Twig_Token::BLOCK_END_TYPE); - - $block = new Twig_Node_Block($name, $body, $lineno); - $this->parser->setBlock($name, $block); - $this->parser->popBlockStack(); - - return new Twig_Node_BlockReference($name, $lineno, $this->getTag()); - } - public function decideBlockEnd($token) - { - return $token->test('endblock'); - } - - public function getTag() - { - return 'block'; - } + public function getTag() + { + return 'block'; + } } diff --git a/lib/Twig/TokenParser/Debug.php b/lib/Twig/TokenParser/Debug.php index 879db6c..1ad985f 100644 --- a/lib/Twig/TokenParser/Debug.php +++ b/lib/Twig/TokenParser/Debug.php @@ -2,22 +2,21 @@ class Twig_TokenParser_Debug extends Twig_TokenParser { - public function parse(Twig_Token $token) - { - $lineno = $token->getLine(); - - $expr = null; - if (!$this->parser->getStream()->test(Twig_Token::BLOCK_END_TYPE)) + public function parse(Twig_Token $token) { - $expr = $this->parser->getExpressionParser()->parseExpression(); - } - $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); + $lineno = $token->getLine(); + + $expr = null; + if (!$this->parser->getStream()->test(Twig_Token::BLOCK_END_TYPE)) { + $expr = $this->parser->getExpressionParser()->parseExpression(); + } + $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); - return new Twig_Node_Debug($expr, $lineno, $this->getTag()); - } + return new Twig_Node_Debug($expr, $lineno, $this->getTag()); + } - public function getTag() - { - return 'debug'; - } + public function getTag() + { + return 'debug'; + } } diff --git a/lib/Twig/TokenParser/Display.php b/lib/Twig/TokenParser/Display.php index 64de493..2d24eef 100644 --- a/lib/Twig/TokenParser/Display.php +++ b/lib/Twig/TokenParser/Display.php @@ -10,21 +10,20 @@ */ class Twig_TokenParser_Display extends Twig_TokenParser { - public function parse(Twig_Token $token) - { - $lineno = $token->getLine(); - $name = $this->parser->getStream()->expect(Twig_Token::NAME_TYPE)->getValue(); - if (!$this->parser->hasBlock($name)) + public function parse(Twig_Token $token) { - throw new Twig_SyntaxError("The block '$name' cannot be displayed as it has not yet been defined", $lineno); - } - $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); + $lineno = $token->getLine(); + $name = $this->parser->getStream()->expect(Twig_Token::NAME_TYPE)->getValue(); + if (!$this->parser->hasBlock($name)) { + throw new Twig_SyntaxError("The block '$name' cannot be displayed as it has not yet been defined", $lineno); + } + $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); - return new Twig_Node_BlockReference($name, $lineno, $this->getTag()); - } + return new Twig_Node_BlockReference($name, $lineno, $this->getTag()); + } - public function getTag() - { - return 'display'; - } + public function getTag() + { + return 'display'; + } } diff --git a/lib/Twig/TokenParser/Extends.php b/lib/Twig/TokenParser/Extends.php index 9fa9f77..deb8164 100644 --- a/lib/Twig/TokenParser/Extends.php +++ b/lib/Twig/TokenParser/Extends.php @@ -11,20 +11,19 @@ */ class Twig_TokenParser_Extends extends Twig_TokenParser { - public function parse(Twig_Token $token) - { - if (null !== $this->parser->getParent()) + public function parse(Twig_Token $token) { - throw new Twig_SyntaxError('Multiple extend tags are forbidden', $token->getLine()); - } - $this->parser->setParent($this->parser->getStream()->expect(Twig_Token::STRING_TYPE)->getValue()); - $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); + if (null !== $this->parser->getParent()) { + throw new Twig_SyntaxError('Multiple extend tags are forbidden', $token->getLine()); + } + $this->parser->setParent($this->parser->getStream()->expect(Twig_Token::STRING_TYPE)->getValue()); + $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); - return null; - } + return null; + } - public function getTag() - { - return 'extends'; - } + public function getTag() + { + return 'extends'; + } } diff --git a/lib/Twig/TokenParser/Filter.php b/lib/Twig/TokenParser/Filter.php index 536311e..29a5a66 100644 --- a/lib/Twig/TokenParser/Filter.php +++ b/lib/Twig/TokenParser/Filter.php @@ -10,25 +10,25 @@ */ class Twig_TokenParser_Filter extends Twig_TokenParser { - public function parse(Twig_Token $token) - { - $lineno = $token->getLine(); - $filters = $this->parser->getExpressionParser()->parseFilterExpressionRaw(); + public function parse(Twig_Token $token) + { + $lineno = $token->getLine(); + $filters = $this->parser->getExpressionParser()->parseFilterExpressionRaw(); - $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); - $body = $this->parser->subparse(array($this, 'decideBlockEnd'), true); - $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); + $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); + $body = $this->parser->subparse(array($this, 'decideBlockEnd'), true); + $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); - return new Twig_Node_Filter($filters, $body, $lineno, $this->getTag()); - } + return new Twig_Node_Filter($filters, $body, $lineno, $this->getTag()); + } - public function decideBlockEnd($token) - { - return $token->test('endfilter'); - } + public function decideBlockEnd($token) + { + return $token->test('endfilter'); + } - public function getTag() - { - return 'filter'; - } + public function getTag() + { + return 'filter'; + } } diff --git a/lib/Twig/TokenParser/For.php b/lib/Twig/TokenParser/For.php index 19c2481..0694089 100644 --- a/lib/Twig/TokenParser/For.php +++ b/lib/Twig/TokenParser/For.php @@ -11,49 +11,45 @@ */ class Twig_TokenParser_For extends Twig_TokenParser { - public function parse(Twig_Token $token) - { - $lineno = $token->getLine(); - list($isMultitarget, $item) = $this->parser->getExpressionParser()->parseAssignmentExpression(); - $this->parser->getStream()->expect('in'); - $seq = $this->parser->getExpressionParser()->parseExpression(); - - $withLoop = true; - if ($this->parser->getStream()->test('without')) + public function parse(Twig_Token $token) { - $this->parser->getStream()->next(); - $this->parser->getStream()->expect('loop'); - $withLoop = false; + $lineno = $token->getLine(); + list($isMultitarget, $item) = $this->parser->getExpressionParser()->parseAssignmentExpression(); + $this->parser->getStream()->expect('in'); + $seq = $this->parser->getExpressionParser()->parseExpression(); + + $withLoop = true; + if ($this->parser->getStream()->test('without')) { + $this->parser->getStream()->next(); + $this->parser->getStream()->expect('loop'); + $withLoop = false; + } + + $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); + $body = $this->parser->subparse(array($this, 'decideForFork')); + if ($this->parser->getStream()->next()->getValue() == 'else') { + $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); + $else = $this->parser->subparse(array($this, 'decideForEnd'), true); + } else { + $else = null; + } + $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); + + return new Twig_Node_For($isMultitarget, $item, $seq, $body, $else, $withLoop, $lineno, $this->getTag()); } - $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); - $body = $this->parser->subparse(array($this, 'decideForFork')); - if ($this->parser->getStream()->next()->getValue() == 'else') + public function decideForFork($token) { - $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); - $else = $this->parser->subparse(array($this, 'decideForEnd'), true); + return $token->test(array('else', 'endfor')); } - else + + public function decideForEnd($token) { - $else = null; + return $token->test('endfor'); } - $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); - return new Twig_Node_For($isMultitarget, $item, $seq, $body, $else, $withLoop, $lineno, $this->getTag()); - } - - public function decideForFork($token) - { - return $token->test(array('else', 'endfor')); - } - - public function decideForEnd($token) - { - return $token->test('endfor'); - } - - public function getTag() - { - return 'for'; - } + public function getTag() + { + return 'for'; + } } diff --git a/lib/Twig/TokenParser/If.php b/lib/Twig/TokenParser/If.php index 9bd4400..b669b17 100644 --- a/lib/Twig/TokenParser/If.php +++ b/lib/Twig/TokenParser/If.php @@ -11,65 +11,61 @@ */ class Twig_TokenParser_If extends Twig_TokenParser { - public function parse(Twig_Token $token) - { - $lineno = $token->getLine(); - $expr = $this->parser->getExpressionParser()->parseExpression(); - $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); - $body = $this->parser->subparse(array($this, 'decideIfFork')); - $tests = array(array($expr, $body)); - $else = null; - - $end = false; - while (!$end) + public function parse(Twig_Token $token) { - try - { - switch ($this->parser->getStream()->next()->getValue()) - { - case 'else': - $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); - $else = $this->parser->subparse(array($this, 'decideIfEnd')); - break; + $lineno = $token->getLine(); + $expr = $this->parser->getExpressionParser()->parseExpression(); + $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); + $body = $this->parser->subparse(array($this, 'decideIfFork')); + $tests = array(array($expr, $body)); + $else = null; + + $end = false; + while (!$end) { + try + { + switch ($this->parser->getStream()->next()->getValue()) { + case 'else': + $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); + $else = $this->parser->subparse(array($this, 'decideIfEnd')); + break; - case 'elseif': - $expr = $this->parser->getExpressionParser()->parseExpression(); - $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); - $body = $this->parser->subparse(array($this, 'decideIfFork')); - $tests[] = array($expr, $body); - break; + case 'elseif': + $expr = $this->parser->getExpressionParser()->parseExpression(); + $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); + $body = $this->parser->subparse(array($this, 'decideIfFork')); + $tests[] = array($expr, $body); + break; - case 'endif': - $end = true; - break; + case 'endif': + $end = true; + break; - default: - throw new Twig_SyntaxError('', -1); + default: + throw new Twig_SyntaxError('', -1); + } + } catch (Twig_SyntaxError $e) { + throw new Twig_SyntaxError(sprintf('Unexpected end of template. Twig was looking for the following tags "else", "elseif", or "endif" to close the "if" block started at line %d)', $lineno), -1); + } } - } - catch (Twig_SyntaxError $e) - { - throw new Twig_SyntaxError(sprintf('Unexpected end of template. Twig was looking for the following tags "else", "elseif", or "endif" to close the "if" block started at line %d)', $lineno), -1); - } - } - $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); + $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); - return new Twig_Node_If($tests, $else, $lineno, $this->getTag()); - } + return new Twig_Node_If($tests, $else, $lineno, $this->getTag()); + } - public function decideIfFork($token) - { - return $token->test(array('elseif', 'else', 'endif')); - } + public function decideIfFork($token) + { + return $token->test(array('elseif', 'else', 'endif')); + } - public function decideIfEnd($token) - { - return $token->test(array('endif')); - } + public function decideIfEnd($token) + { + return $token->test(array('endif')); + } - public function getTag() - { - return 'if'; - } + public function getTag() + { + return 'if'; + } } diff --git a/lib/Twig/TokenParser/Import.php b/lib/Twig/TokenParser/Import.php index e3a3c2c..0f464c0 100644 --- a/lib/Twig/TokenParser/Import.php +++ b/lib/Twig/TokenParser/Import.php @@ -10,18 +10,18 @@ */ class Twig_TokenParser_Import extends Twig_TokenParser { - public function parse(Twig_Token $token) - { - $macro = $this->parser->getStream()->expect(Twig_Token::STRING_TYPE)->getValue(); - $this->parser->getStream()->expect('as'); - $var = $this->parser->getStream()->expect(Twig_Token::NAME_TYPE)->getValue(); - $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); + public function parse(Twig_Token $token) + { + $macro = $this->parser->getStream()->expect(Twig_Token::STRING_TYPE)->getValue(); + $this->parser->getStream()->expect('as'); + $var = $this->parser->getStream()->expect(Twig_Token::NAME_TYPE)->getValue(); + $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); - return new Twig_Node_Import($macro, $var, $token->getLine(), $this->getTag()); - } + return new Twig_Node_Import($macro, $var, $token->getLine(), $this->getTag()); + } - public function getTag() - { - return 'import'; - } + public function getTag() + { + return 'import'; + } } diff --git a/lib/Twig/TokenParser/Include.php b/lib/Twig/TokenParser/Include.php index 9e007c8..963c243 100644 --- a/lib/Twig/TokenParser/Include.php +++ b/lib/Twig/TokenParser/Include.php @@ -11,31 +11,29 @@ */ class Twig_TokenParser_Include extends Twig_TokenParser { - public function parse(Twig_Token $token) - { - $expr = $this->parser->getExpressionParser()->parseExpression(); - - $sandboxed = false; - if ($this->parser->getStream()->test(Twig_Token::NAME_TYPE, 'sandboxed')) + public function parse(Twig_Token $token) { - $this->parser->getStream()->next(); - $sandboxed = true; - } + $expr = $this->parser->getExpressionParser()->parseExpression(); - $variables = null; - if ($this->parser->getStream()->test(Twig_Token::NAME_TYPE, 'with')) - { - $this->parser->getStream()->next(); - $variables = $this->parser->getExpressionParser()->parseExpression(); - } + $sandboxed = false; + if ($this->parser->getStream()->test(Twig_Token::NAME_TYPE, 'sandboxed')) { + $this->parser->getStream()->next(); + $sandboxed = true; + } - $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); + $variables = null; + if ($this->parser->getStream()->test(Twig_Token::NAME_TYPE, 'with')) { + $this->parser->getStream()->next(); + $variables = $this->parser->getExpressionParser()->parseExpression(); + } - return new Twig_Node_Include($expr, $sandboxed, $variables, $token->getLine(), $this->getTag()); - } + $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); - public function getTag() - { - return 'include'; - } + return new Twig_Node_Include($expr, $sandboxed, $variables, $token->getLine(), $this->getTag()); + } + + public function getTag() + { + return 'include'; + } } diff --git a/lib/Twig/TokenParser/Macro.php b/lib/Twig/TokenParser/Macro.php index 3f1efc6..567ecfa 100644 --- a/lib/Twig/TokenParser/Macro.php +++ b/lib/Twig/TokenParser/Macro.php @@ -10,29 +10,29 @@ */ class Twig_TokenParser_Macro extends Twig_TokenParser { - public function parse(Twig_Token $token) - { - $lineno = $token->getLine(); - $name = $this->parser->getStream()->expect(Twig_Token::NAME_TYPE)->getValue(); + public function parse(Twig_Token $token) + { + $lineno = $token->getLine(); + $name = $this->parser->getStream()->expect(Twig_Token::NAME_TYPE)->getValue(); - $arguments = $this->parser->getExpressionParser()->parseArguments(); + $arguments = $this->parser->getExpressionParser()->parseArguments(); - $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); - $body = $this->parser->subparse(array($this, 'decideBlockEnd'), true); - $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); + $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); + $body = $this->parser->subparse(array($this, 'decideBlockEnd'), true); + $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); - $this->parser->setMacro($name, new Twig_Node_Macro($name, $body, $arguments, $lineno, $this->getTag())); + $this->parser->setMacro($name, new Twig_Node_Macro($name, $body, $arguments, $lineno, $this->getTag())); - return null; - } + return null; + } - public function decideBlockEnd($token) - { - return $token->test('endmacro'); - } + public function decideBlockEnd($token) + { + return $token->test('endmacro'); + } - public function getTag() - { - return 'macro'; - } + public function getTag() + { + return 'macro'; + } } diff --git a/lib/Twig/TokenParser/Parent.php b/lib/Twig/TokenParser/Parent.php index 5cd7b98..c157cef 100644 --- a/lib/Twig/TokenParser/Parent.php +++ b/lib/Twig/TokenParser/Parent.php @@ -11,19 +11,18 @@ */ class Twig_TokenParser_Parent extends Twig_TokenParser { - public function parse(Twig_Token $token) - { - if (!count($this->parser->getBlockStack())) + public function parse(Twig_Token $token) { - throw new Twig_SyntaxError('Calling "parent" outside a block is forbidden', $token->getLine()); - } - $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); + if (!count($this->parser->getBlockStack())) { + throw new Twig_SyntaxError('Calling "parent" outside a block is forbidden', $token->getLine()); + } + $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); - return new Twig_Node_Parent($this->parser->peekBlockStack(), $token->getLine(), $this->getTag()); - } + return new Twig_Node_Parent($this->parser->peekBlockStack(), $token->getLine(), $this->getTag()); + } - public function getTag() - { - return 'parent'; - } + public function getTag() + { + return 'parent'; + } } diff --git a/lib/Twig/TokenParser/Set.php b/lib/Twig/TokenParser/Set.php index 63d97a8..6707e9b 100644 --- a/lib/Twig/TokenParser/Set.php +++ b/lib/Twig/TokenParser/Set.php @@ -10,50 +10,45 @@ */ class Twig_TokenParser_Set extends Twig_TokenParser { - public function parse(Twig_Token $token) - { - $lineno = $token->getLine(); - $stream = $this->parser->getStream(); - list($isMultitarget, $names) = $this->parser->getExpressionParser()->parseAssignmentExpression(); - - $capture = false; - if ($stream->test(Twig_Token::NAME_TYPE, 'as')) + public function parse(Twig_Token $token) { - $stream->expect(Twig_Token::NAME_TYPE, 'as'); - list(, $values) = $this->parser->getExpressionParser()->parseMultitargetExpression(); + $lineno = $token->getLine(); + $stream = $this->parser->getStream(); + list($isMultitarget, $names) = $this->parser->getExpressionParser()->parseAssignmentExpression(); - $stream->expect(Twig_Token::BLOCK_END_TYPE); - } - else - { - $capture = true; + $capture = false; + if ($stream->test(Twig_Token::NAME_TYPE, 'as')) { + $stream->expect(Twig_Token::NAME_TYPE, 'as'); + list(, $values) = $this->parser->getExpressionParser()->parseMultitargetExpression(); + + $stream->expect(Twig_Token::BLOCK_END_TYPE); + } else { + $capture = true; + + if ($isMultitarget) { + throw new Twig_SyntaxError("When using set with a block, you cannot have a multi-target.", $lineno); + } + + $stream->expect(Twig_Token::BLOCK_END_TYPE); - if ($isMultitarget) - { - throw new Twig_SyntaxError("When using set with a block, you cannot have a multi-target.", $lineno); - } + $values = $this->parser->subparse(array($this, 'decideBlockEnd'), true); + $stream->expect(Twig_Token::BLOCK_END_TYPE); + } - $stream->expect(Twig_Token::BLOCK_END_TYPE); + if (count($names) !== count($values)) { + throw new Twig_SyntaxError("When using set, you must have the same number of variables and assignements.", $lineno); + } - $values = $this->parser->subparse(array($this, 'decideBlockEnd'), true); - $stream->expect(Twig_Token::BLOCK_END_TYPE); + return new Twig_Node_Set($isMultitarget, $capture, $names, $values, $lineno, $this->getTag()); } - if (count($names) !== count($values)) + public function decideBlockEnd($token) { - throw new Twig_SyntaxError("When using set, you must have the same number of variables and assignements.", $lineno); + return $token->test('endset'); } - return new Twig_Node_Set($isMultitarget, $capture, $names, $values, $lineno, $this->getTag()); - } - - public function decideBlockEnd($token) - { - return $token->test('endset'); - } - - public function getTag() - { - return 'set'; - } + public function getTag() + { + return 'set'; + } } diff --git a/lib/Twig/TokenParser/Trans.php b/lib/Twig/TokenParser/Trans.php index 557b8ed..615972a 100644 --- a/lib/Twig/TokenParser/Trans.php +++ b/lib/Twig/TokenParser/Trans.php @@ -10,46 +10,43 @@ */ class Twig_TokenParser_Trans extends Twig_TokenParser { - public function parse(Twig_Token $token) - { - $lineno = $token->getLine(); - $stream = $this->parser->getStream(); - $count = false; - if (!$stream->test(Twig_Token::BLOCK_END_TYPE)) + public function parse(Twig_Token $token) { - $count = new Twig_Node_Expression_Name($stream->expect(Twig_Token::NAME_TYPE)->getValue(), $lineno); - } + $lineno = $token->getLine(); + $stream = $this->parser->getStream(); + $count = false; + if (!$stream->test(Twig_Token::BLOCK_END_TYPE)) { + $count = new Twig_Node_Expression_Name($stream->expect(Twig_Token::NAME_TYPE)->getValue(), $lineno); + } - $stream->expect(Twig_Token::BLOCK_END_TYPE); - $body = $this->parser->subparse(array($this, 'decideForFork')); - $plural = false; - if ('plural' === $stream->next()->getValue()) - { - $stream->expect(Twig_Token::BLOCK_END_TYPE); - $plural = $this->parser->subparse(array($this, 'decideForEnd'), true); + $stream->expect(Twig_Token::BLOCK_END_TYPE); + $body = $this->parser->subparse(array($this, 'decideForFork')); + $plural = false; + if ('plural' === $stream->next()->getValue()) { + $stream->expect(Twig_Token::BLOCK_END_TYPE); + $plural = $this->parser->subparse(array($this, 'decideForEnd'), true); - if (false === $count) - { - throw new Twig_SyntaxError('When a plural is used, you must pass the count as an argument to the "trans" tag', $lineno); - } - } - $stream->expect(Twig_Token::BLOCK_END_TYPE); + if (false === $count) { + throw new Twig_SyntaxError('When a plural is used, you must pass the count as an argument to the "trans" tag', $lineno); + } + } + $stream->expect(Twig_Token::BLOCK_END_TYPE); - return new Twig_Node_Trans($count, $body, $plural, $lineno, $this->getTag()); - } + return new Twig_Node_Trans($count, $body, $plural, $lineno, $this->getTag()); + } - public function decideForFork($token) - { - return $token->test(array('plural', 'endtrans')); - } + public function decideForFork($token) + { + return $token->test(array('plural', 'endtrans')); + } - public function decideForEnd($token) - { - return $token->test('endtrans'); - } + public function decideForEnd($token) + { + return $token->test('endtrans'); + } - public function getTag() - { - return 'trans'; - } + public function getTag() + { + return 'trans'; + } } diff --git a/lib/Twig/TokenStream.php b/lib/Twig/TokenStream.php index 74e1537..5974014 100644 --- a/lib/Twig/TokenStream.php +++ b/lib/Twig/TokenStream.php @@ -11,158 +11,150 @@ */ class Twig_TokenStream { - protected $pushed; - protected $originalTokens; - protected $tokens; - protected $eof; - protected $current; - protected $filename; - protected $trimBlocks; - - public function __construct(array $tokens, $filename, $trimBlocks = true) - { - $this->pushed = array(); - $this->originalTokens = $tokens; - $this->tokens = $tokens; - $this->filename = $filename; - $this->trimBlocks = $trimBlocks; - $this->next(); - } - - public function __toString() - { - $repr = ''; - foreach ($this->originalTokens as $token) + protected $pushed; + protected $originalTokens; + protected $tokens; + protected $eof; + protected $current; + protected $filename; + protected $trimBlocks; + + public function __construct(array $tokens, $filename, $trimBlocks = true) { - $repr .= $token."\n"; + $this->pushed = array(); + $this->originalTokens = $tokens; + $this->tokens = $tokens; + $this->filename = $filename; + $this->trimBlocks = $trimBlocks; + $this->next(); } - return $repr; - } - - public function push($token) - { - $this->pushed[] = $token; - } - - /** - * Sets the pointer to the next token and returns the old one. - * - * @param Boolean $fromStack Whether to get a token from the stack or not - */ - public function next($fromStack = true) - { - if ($fromStack && !empty($this->pushed)) + public function __toString() { - $old = array_shift($this->pushed); - $token = array_shift($this->pushed); + $repr = ''; + foreach ($this->originalTokens as $token) { + $repr .= $token."\n"; + } + + return $repr; } - else + + public function push($token) { - $old = $this->current; - $token = array_shift($this->tokens); + $this->pushed[] = $token; } - if (null === $token) + /** + * Sets the pointer to the next token and returns the old one. + * + * @param Boolean $fromStack Whether to get a token from the stack or not + */ + public function next($fromStack = true) { - throw new Twig_SyntaxError('Unexpected end of template', -1); + if ($fromStack && !empty($this->pushed)) { + $old = array_shift($this->pushed); + $token = array_shift($this->pushed); + } else { + $old = $this->current; + $token = array_shift($this->tokens); + } + + if (null === $token) { + throw new Twig_SyntaxError('Unexpected end of template', -1); + } + + // trim blocks + if ($this->trimBlocks && + $this->current && + Twig_Token::BLOCK_END_TYPE === $this->current->getType() && + Twig_Token::TEXT_TYPE === $token->getType() && + $token->getValue() && + "\n" === substr($token->getValue(), 0, 1) + ) + { + $value = substr($token->getValue(), 1); + + if (!$value) { + return $this->next(); + } + + $token->setValue($value); + } + + $this->current = $token; + + $this->eof = $token->getType() === Twig_Token::EOF_TYPE; + + return $old; } - // trim blocks - if ($this->trimBlocks && - $this->current && - Twig_Token::BLOCK_END_TYPE === $this->current->getType() && - Twig_Token::TEXT_TYPE === $token->getType() && - $token->getValue() && - "\n" === substr($token->getValue(), 0, 1) - ) + /** + * Looks at the next token. + */ + public function look() { - $value = substr($token->getValue(), 1); + $old = $this->next(false); + $new = $this->current; + $this->push($old); + $this->push($new); - if (!$value) - { - return $this->next(); - } + return $new; + } - $token->setValue($value); + /** + * Rewinds the pushed tokens. + */ + public function rewind() + { + $tokens = array(); + while ($this->pushed) { + $tokens[] = array_shift($this->pushed); + array_shift($this->pushed); + } + + $this->tokens = array_merge($tokens, array($this->current), $this->tokens); + + $this->next(); } - $this->current = $token; - - $this->eof = $token->getType() === Twig_Token::EOF_TYPE; - - return $old; - } - - /** - * Looks at the next token. - */ - public function look() - { - $old = $this->next(false); - $new = $this->current; - $this->push($old); - $this->push($new); - - return $new; - } - - /** - * Rewinds the pushed tokens. - */ - public function rewind() - { - $tokens = array(); - while ($this->pushed) + /** + * Expects a token (like $token->test()) and returns it or throw a syntax error. + */ + public function expect($primary, $secondary = null) { - $tokens[] = array_shift($this->pushed); - array_shift($this->pushed); + $token = $this->current; + if (!$token->test($primary, $secondary)) { + throw new Twig_SyntaxError(sprintf('Unexpected token "%s" of value "%s" ("%s" expected%s)', + Twig_Token::getTypeAsString($token->getType()), $token->getValue(), + Twig_Token::getTypeAsString($primary), $secondary ? sprintf(' with value "%s"', $secondary) : ''), + $this->current->getLine() + ); + } + $this->next(); + + return $token; } - $this->tokens = array_merge($tokens, array($this->current), $this->tokens); + /** + * Forwards that call to the current token. + */ + public function test($primary, $secondary = null) + { + return $this->current->test($primary, $secondary); + } + + public function isEOF() + { + return $this->eof; + } - $this->next(); - } + public function getCurrent() + { + return $this->current; + } - /** - * Expects a token (like $token->test()) and returns it or throw a syntax error. - */ - public function expect($primary, $secondary = null) - { - $token = $this->current; - if (!$token->test($primary, $secondary)) + public function getFilename() { - throw new Twig_SyntaxError(sprintf('Unexpected token "%s" of value "%s" ("%s" expected%s)', - Twig_Token::getTypeAsString($token->getType()), $token->getValue(), - Twig_Token::getTypeAsString($primary), $secondary ? sprintf(' with value "%s"', $secondary) : ''), - $this->current->getLine() - ); + return $this->filename; } - $this->next(); - - return $token; - } - - /** - * Forwards that call to the current token. - */ - public function test($primary, $secondary = null) - { - return $this->current->test($primary, $secondary); - } - - public function isEOF() - { - return $this->eof; - } - - public function getCurrent() - { - return $this->current; - } - - public function getFilename() - { - return $this->filename; - } } diff --git a/test/Twig/Tests/AutoloaderTest.php b/test/Twig/Tests/AutoloaderTest.php index cfb6e12..cf696c9 100644 --- a/test/Twig/Tests/AutoloaderTest.php +++ b/test/Twig/Tests/AutoloaderTest.php @@ -13,12 +13,12 @@ require_once dirname(__FILE__).'/bootstrap.php'; class Twig_Tests_AutoloaderTest extends PHPUnit_Framework_TestCase { - public function testAutoload() - { - $this->assertFalse(class_exists('FooBarFoo'), '->autoload() does not try to load classes that does not begin with Twig'); + public function testAutoload() + { + $this->assertFalse(class_exists('FooBarFoo'), '->autoload() does not try to load classes that does not begin with Twig'); - $autoloader = new Twig_Autoloader(); - $this->assertTrue($autoloader->autoload('Twig_Parser'), '->autoload() returns true if it is able to load a class'); - $this->assertFalse($autoloader->autoload('Foo'), '->autoload() returns false if it is not able to load a class'); - } + $autoloader = new Twig_Autoloader(); + $this->assertTrue($autoloader->autoload('Twig_Parser'), '->autoload() returns true if it is able to load a class'); + $this->assertFalse($autoloader->autoload('Foo'), '->autoload() returns false if it is not able to load a class'); + } } diff --git a/test/Twig/Tests/Extension/SandboxTest.php b/test/Twig/Tests/Extension/SandboxTest.php index d2f9938..21785b7 100644 --- a/test/Twig/Tests/Extension/SandboxTest.php +++ b/test/Twig/Tests/Extension/SandboxTest.php @@ -13,126 +13,111 @@ require_once dirname(__FILE__).'/../bootstrap.php'; class Twig_Tests_Extension_SandboxTest extends PHPUnit_Framework_TestCase { - static protected $params, $templates; - - public function setUp() - { - self::$params = array( - 'name' => 'Fabien', - 'obj' => new Object(), - ); - - self::$templates = array( - '1_basic1' => '{{ obj.foo }}', - '1_basic2' => '{{ name|upper }}', - '1_basic3' => '{% if name %}foo{% endif %}', - '1_basic4' => '{{ obj.bar }}', - '1_basic' => '{% if obj.foo %}{{ obj.foo|upper }}{% endif %}', - ); - } - - public function testSandboxGloballySet() - { - $twig = $this->getEnvironment(false, self::$templates); - $this->assertEquals('FOO', $twig->loadTemplate('1_basic')->render(self::$params), 'Sandbox does nothing if it is disabled globally'); - - $twig = $this->getEnvironment(true, self::$templates); - try - { - $twig->loadTemplate('1_basic1')->render(self::$params); - $this->fail('Sandbox throws a SecurityError exception if an unallowed method is called'); - } - catch (Twig_Sandbox_SecurityError $e) - { - } + static protected $params, $templates; - $twig = $this->getEnvironment(true, self::$templates); - try - { - $twig->loadTemplate('1_basic2')->render(self::$params); - $this->fail('Sandbox throws a SecurityError exception if an unallowed filter is called'); - } - catch (Twig_Sandbox_SecurityError $e) + public function setUp() { + self::$params = array( + 'name' => 'Fabien', + 'obj' => new Object(), + ); + + self::$templates = array( + '1_basic1' => '{{ obj.foo }}', + '1_basic2' => '{{ name|upper }}', + '1_basic3' => '{% if name %}foo{% endif %}', + '1_basic4' => '{{ obj.bar }}', + '1_basic' => '{% if obj.foo %}{{ obj.foo|upper }}{% endif %}', + ); } - $twig = $this->getEnvironment(true, self::$templates); - try - { - $twig->loadTemplate('1_basic3')->render(self::$params); - $this->fail('Sandbox throws a SecurityError exception if an unallowed tag is used in the template'); - } - catch (Twig_Sandbox_SecurityError $e) + public function testSandboxGloballySet() { + $twig = $this->getEnvironment(false, self::$templates); + $this->assertEquals('FOO', $twig->loadTemplate('1_basic')->render(self::$params), 'Sandbox does nothing if it is disabled globally'); + + $twig = $this->getEnvironment(true, self::$templates); + try { + $twig->loadTemplate('1_basic1')->render(self::$params); + $this->fail('Sandbox throws a SecurityError exception if an unallowed method is called'); + } catch (Twig_Sandbox_SecurityError $e) { + } + + $twig = $this->getEnvironment(true, self::$templates); + try { + $twig->loadTemplate('1_basic2')->render(self::$params); + $this->fail('Sandbox throws a SecurityError exception if an unallowed filter is called'); + } catch (Twig_Sandbox_SecurityError $e) { + } + + $twig = $this->getEnvironment(true, self::$templates); + try { + $twig->loadTemplate('1_basic3')->render(self::$params); + $this->fail('Sandbox throws a SecurityError exception if an unallowed tag is used in the template'); + } catch (Twig_Sandbox_SecurityError $e) { + } + + $twig = $this->getEnvironment(true, self::$templates); + try { + $twig->loadTemplate('1_basic4')->render(self::$params); + $this->fail('Sandbox throws a SecurityError exception if an unallowed property is called in the template'); + } catch (Twig_Sandbox_SecurityError $e) { + } + + $twig = $this->getEnvironment(true, self::$templates, array(), array(), array('Object' => 'foo')); + $this->assertEquals('foo', $twig->loadTemplate('1_basic1')->render(self::$params), 'Sandbox allow some methods'); + + $twig = $this->getEnvironment(true, self::$templates, array(), array('upper')); + $this->assertEquals('FABIEN', $twig->loadTemplate('1_basic2')->render(self::$params), 'Sandbox allow some filters'); + + $twig = $this->getEnvironment(true, self::$templates, array('if')); + $this->assertEquals('foo', $twig->loadTemplate('1_basic3')->render(self::$params), 'Sandbox allow some tags'); + + $twig = $this->getEnvironment(true, self::$templates, array(), array(), array(), array('Object' => 'bar')); + $this->assertEquals('bar', $twig->loadTemplate('1_basic4')->render(self::$params), 'Sandbox allow some properties'); } - $twig = $this->getEnvironment(true, self::$templates); - try - { - $twig->loadTemplate('1_basic4')->render(self::$params); - $this->fail('Sandbox throws a SecurityError exception if an unallowed property is called in the template'); - } - catch (Twig_Sandbox_SecurityError $e) + public function testSandboxLocallySetForAnInclude() { + self::$templates = array( + '2_basic' => '{{ obj.foo }}{% include "2_included" %}{{ obj.foo }}', + '2_included' => '{% if obj.foo %}{{ obj.foo|upper }}{% endif %}', + ); + + $twig = $this->getEnvironment(false, self::$templates); + $this->assertEquals('fooFOOfoo', $twig->loadTemplate('2_basic')->render(self::$params), 'Sandbox does nothing if disabled globally and sandboxed not used for the include'); + + self::$templates = array( + '3_basic' => '{{ obj.foo }}{% include "3_included" sandboxed %}{{ obj.foo }}', + '3_included' => '{% if obj.foo %}{{ obj.foo|upper }}{% endif %}', + ); + + $twig = $this->getEnvironment(false, self::$templates); + $twig = $this->getEnvironment(true, self::$templates); + try { + $twig->loadTemplate('3_basic')->render(self::$params); + $this->fail('Sandbox throws a SecurityError exception when the included file is sandboxed'); + } catch (Twig_Sandbox_SecurityError $e) { + } } - $twig = $this->getEnvironment(true, self::$templates, array(), array(), array('Object' => 'foo')); - $this->assertEquals('foo', $twig->loadTemplate('1_basic1')->render(self::$params), 'Sandbox allow some methods'); - - $twig = $this->getEnvironment(true, self::$templates, array(), array('upper')); - $this->assertEquals('FABIEN', $twig->loadTemplate('1_basic2')->render(self::$params), 'Sandbox allow some filters'); - - $twig = $this->getEnvironment(true, self::$templates, array('if')); - $this->assertEquals('foo', $twig->loadTemplate('1_basic3')->render(self::$params), 'Sandbox allow some tags'); - - $twig = $this->getEnvironment(true, self::$templates, array(), array(), array(), array('Object' => 'bar')); - $this->assertEquals('bar', $twig->loadTemplate('1_basic4')->render(self::$params), 'Sandbox allow some properties'); - } - - public function testSandboxLocallySetForAnInclude() - { - self::$templates = array( - '2_basic' => '{{ obj.foo }}{% include "2_included" %}{{ obj.foo }}', - '2_included' => '{% if obj.foo %}{{ obj.foo|upper }}{% endif %}', - ); - - $twig = $this->getEnvironment(false, self::$templates); - $this->assertEquals('fooFOOfoo', $twig->loadTemplate('2_basic')->render(self::$params), 'Sandbox does nothing if disabled globally and sandboxed not used for the include'); - - self::$templates = array( - '3_basic' => '{{ obj.foo }}{% include "3_included" sandboxed %}{{ obj.foo }}', - '3_included' => '{% if obj.foo %}{{ obj.foo|upper }}{% endif %}', - ); - - $twig = $this->getEnvironment(false, self::$templates); - $twig = $this->getEnvironment(true, self::$templates); - try - { - $twig->loadTemplate('3_basic')->render(self::$params); - $this->fail('Sandbox throws a SecurityError exception when the included file is sandboxed'); - } - catch (Twig_Sandbox_SecurityError $e) + protected function getEnvironment($sandboxed, $templates, $tags = array(), $filters = array(), $methods = array(), $properties = array()) { - } - } - - protected function getEnvironment($sandboxed, $templates, $tags = array(), $filters = array(), $methods = array(), $properties = array()) - { - $loader = new Twig_Loader_Array($templates); - $twig = new Twig_Environment($loader, array('trim_blocks' => true, 'debug' => true)); - $policy = new Twig_Sandbox_SecurityPolicy($tags, $filters, $methods, $properties); - $twig->addExtension(new Twig_Extension_Sandbox($policy, $sandboxed)); + $loader = new Twig_Loader_Array($templates); + $twig = new Twig_Environment($loader, array('trim_blocks' => true, 'debug' => true)); + $policy = new Twig_Sandbox_SecurityPolicy($tags, $filters, $methods, $properties); + $twig->addExtension(new Twig_Extension_Sandbox($policy, $sandboxed)); - return $twig; - } + return $twig; + } } class Object { - public $bar = 'bar'; + public $bar = 'bar'; - public function foo() - { - return 'foo'; - } + public function foo() + { + return 'foo'; + } } diff --git a/test/Twig/Tests/TokenStreamTest.php b/test/Twig/Tests/TokenStreamTest.php index 43362cf..11a1f2e 100644 --- a/test/Twig/Tests/TokenStreamTest.php +++ b/test/Twig/Tests/TokenStreamTest.php @@ -13,78 +13,74 @@ require_once dirname(__FILE__).'/bootstrap.php'; class Twig_Tests_TokenStreamTest extends PHPUnit_Framework_TestCase { - static protected $tokens; + static protected $tokens; - public function setUp() - { - self::$tokens = array( - new Twig_Token(Twig_Token::TEXT_TYPE, 1, 0), - new Twig_Token(Twig_Token::TEXT_TYPE, 2, 0), - new Twig_Token(Twig_Token::TEXT_TYPE, 3, 0), - new Twig_Token(Twig_Token::TEXT_TYPE, 4, 0), - new Twig_Token(Twig_Token::TEXT_TYPE, 5, 0), - new Twig_Token(Twig_Token::TEXT_TYPE, 6, 0), - new Twig_Token(Twig_Token::TEXT_TYPE, 7, 0), - new Twig_Token(Twig_Token::EOF_TYPE, 0, 0), - ); - } - - public function testNext() - { - $stream = new Twig_TokenStream(self::$tokens, '', false); - $repr = array(); - while (!$stream->isEOF()) + public function setUp() { - $token = $stream->next(); - - $repr[] = $token->getValue(); + self::$tokens = array( + new Twig_Token(Twig_Token::TEXT_TYPE, 1, 0), + new Twig_Token(Twig_Token::TEXT_TYPE, 2, 0), + new Twig_Token(Twig_Token::TEXT_TYPE, 3, 0), + new Twig_Token(Twig_Token::TEXT_TYPE, 4, 0), + new Twig_Token(Twig_Token::TEXT_TYPE, 5, 0), + new Twig_Token(Twig_Token::TEXT_TYPE, 6, 0), + new Twig_Token(Twig_Token::TEXT_TYPE, 7, 0), + new Twig_Token(Twig_Token::EOF_TYPE, 0, 0), + ); } - $this->assertEquals('1, 2, 3, 4, 5, 6, 7', implode(', ', $repr), '->next() returns the next token in the stream'); - } - public function testLook() - { - $stream = new Twig_TokenStream(self::$tokens, '', false); - $this->assertEquals(2, $stream->look()->getValue(), '->look() returns the next token'); - $repr = array(); - while (!$stream->isEOF()) + public function testNext() { - $token = $stream->next(); + $stream = new Twig_TokenStream(self::$tokens, '', false); + $repr = array(); + while (!$stream->isEOF()) { + $token = $stream->next(); - $repr[] = $token->getValue(); + $repr[] = $token->getValue(); + } + $this->assertEquals('1, 2, 3, 4, 5, 6, 7', implode(', ', $repr), '->next() returns the next token in the stream'); } - $this->assertEquals('1, 2, 3, 4, 5, 6, 7', implode(', ', $repr), '->look() pushes the token to the stack'); - $stream = new Twig_TokenStream(self::$tokens, '', false); - $this->assertEquals(2, $stream->look()->getValue(), '->look() returns the next token'); - $this->assertEquals(3, $stream->look()->getValue(), '->look() can be called several times to look more than one upcoming token'); - $this->assertEquals(4, $stream->look()->getValue(), '->look() can be called several times to look more than one upcoming token'); - $this->assertEquals(5, $stream->look()->getValue(), '->look() can be called several times to look more than one upcoming token'); - $repr = array(); - while (!$stream->isEOF()) + public function testLook() { - $token = $stream->next(); + $stream = new Twig_TokenStream(self::$tokens, '', false); + $this->assertEquals(2, $stream->look()->getValue(), '->look() returns the next token'); + $repr = array(); + while (!$stream->isEOF()) { + $token = $stream->next(); + + $repr[] = $token->getValue(); + } + $this->assertEquals('1, 2, 3, 4, 5, 6, 7', implode(', ', $repr), '->look() pushes the token to the stack'); + + $stream = new Twig_TokenStream(self::$tokens, '', false); + $this->assertEquals(2, $stream->look()->getValue(), '->look() returns the next token'); + $this->assertEquals(3, $stream->look()->getValue(), '->look() can be called several times to look more than one upcoming token'); + $this->assertEquals(4, $stream->look()->getValue(), '->look() can be called several times to look more than one upcoming token'); + $this->assertEquals(5, $stream->look()->getValue(), '->look() can be called several times to look more than one upcoming token'); + $repr = array(); + while (!$stream->isEOF()) { + $token = $stream->next(); - $repr[] = $token->getValue(); + $repr[] = $token->getValue(); + } + $this->assertEquals('1, 2, 3, 4, 5, 6, 7', implode(', ', $repr), '->look() pushes the token to the stack'); } - $this->assertEquals('1, 2, 3, 4, 5, 6, 7', implode(', ', $repr), '->look() pushes the token to the stack'); - } - public function testRewind() - { - $stream = new Twig_TokenStream(self::$tokens, '', false); - $this->assertEquals(2, $stream->look()->getValue(), '->look() returns the next token'); - $this->assertEquals(3, $stream->look()->getValue(), '->look() can be called several times to look more than one upcoming token'); - $this->assertEquals(4, $stream->look()->getValue(), '->look() can be called several times to look more than one upcoming token'); - $this->assertEquals(5, $stream->look()->getValue(), '->look() can be called several times to look more than one upcoming token'); - $stream->rewind(); - $repr = array(); - while (!$stream->isEOF()) + public function testRewind() { - $token = $stream->next(false); + $stream = new Twig_TokenStream(self::$tokens, '', false); + $this->assertEquals(2, $stream->look()->getValue(), '->look() returns the next token'); + $this->assertEquals(3, $stream->look()->getValue(), '->look() can be called several times to look more than one upcoming token'); + $this->assertEquals(4, $stream->look()->getValue(), '->look() can be called several times to look more than one upcoming token'); + $this->assertEquals(5, $stream->look()->getValue(), '->look() can be called several times to look more than one upcoming token'); + $stream->rewind(); + $repr = array(); + while (!$stream->isEOF()) { + $token = $stream->next(false); - $repr[] = $token->getValue(); + $repr[] = $token->getValue(); + } + $this->assertEquals('1, 2, 3, 4, 5, 6, 7', implode(', ', $repr), '->rewind() pushes all pushed tokens to the token array'); } - $this->assertEquals('1, 2, 3, 4, 5, 6, 7', implode(', ', $repr), '->rewind() pushes all pushed tokens to the token array'); - } } diff --git a/test/Twig/Tests/integrationTest.php b/test/Twig/Tests/integrationTest.php index b2c11e9..1932c5d 100644 --- a/test/Twig/Tests/integrationTest.php +++ b/test/Twig/Tests/integrationTest.php @@ -13,98 +13,91 @@ require_once dirname(__FILE__).'/bootstrap.php'; class Twig_Tests_IntegrationTest extends PHPUnit_Framework_TestCase { - static protected $fixturesDir; + static protected $fixturesDir; - public function setUp() - { - self::$fixturesDir = realpath(dirname(__FILE__).'/../../fixtures/'); - } + public function setUp() + { + self::$fixturesDir = realpath(dirname(__FILE__).'/../../fixtures/'); + } - public function testIntegration() - { - foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator(self::$fixturesDir), RecursiveIteratorIterator::LEAVES_ONLY) as $file) + public function testIntegration() { - if (!preg_match('/\.test$/', $file)) - { - continue; - } - - $test = file_get_contents($file->getRealpath()); - - if (!preg_match('/--TEST--\s*(.*?)\s*((?:--TEMPLATE(?:\(.*?\))?--(?:.*?))+)--DATA--.*?--EXPECT--.*/s', $test, $match)) - { - throw new InvalidArgumentException(sprintf('Test "%s" is not valid.', str_replace(self::$fixturesDir.'/', '', $file))); - } - - $message = $match[1]; - $templates = array(); - preg_match_all('/--TEMPLATE(?:\((.*?)\))?--(.*?)(?=\-\-TEMPLATE|$)/s', $match[2], $matches, PREG_SET_ORDER); - foreach ($matches as $match) - { - $templates[($match[1] ? $match[1] : 'index.twig')] = $match[2]; - } - - $loader = new Twig_Loader_Array($templates); - $twig = new Twig_Environment($loader, array('trim_blocks' => true, 'cache' => false)); - $twig->addExtension(new Twig_Extension_Escaper()); - $twig->addExtension(new TestExtension()); - - $template = $twig->loadTemplate('index.twig'); - - preg_match_all('/--DATA--(.*?)--EXPECT--(.*?)(?=\-\-DATA\-\-|$)/s', $test, $matches, PREG_SET_ORDER); - foreach ($matches as $match) - { - $output = trim($template->render(eval($match[1].';')), "\n "); - $expected = trim($match[2], "\n "); - - $this->assertEquals($expected, $output, $message); - if ($output != $expected) - { - echo 'Compiled template that failed:'; - - foreach (array_keys($templates) as $name) - { - $source = $loader->getSource($name); - echo $twig->compile($twig->parse($twig->tokenize($source, $name))); - } + foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator(self::$fixturesDir), RecursiveIteratorIterator::LEAVES_ONLY) as $file) { + if (!preg_match('/\.test$/', $file)) { + continue; + } + + $test = file_get_contents($file->getRealpath()); + + if (!preg_match('/--TEST--\s*(.*?)\s*((?:--TEMPLATE(?:\(.*?\))?--(?:.*?))+)--DATA--.*?--EXPECT--.*/s', $test, $match)) { + throw new InvalidArgumentException(sprintf('Test "%s" is not valid.', str_replace(self::$fixturesDir.'/', '', $file))); + } + + $message = $match[1]; + $templates = array(); + preg_match_all('/--TEMPLATE(?:\((.*?)\))?--(.*?)(?=\-\-TEMPLATE|$)/s', $match[2], $matches, PREG_SET_ORDER); + foreach ($matches as $match) { + $templates[($match[1] ? $match[1] : 'index.twig')] = $match[2]; + } + + $loader = new Twig_Loader_Array($templates); + $twig = new Twig_Environment($loader, array('trim_blocks' => true, 'cache' => false)); + $twig->addExtension(new Twig_Extension_Escaper()); + $twig->addExtension(new TestExtension()); + + $template = $twig->loadTemplate('index.twig'); + + preg_match_all('/--DATA--(.*?)--EXPECT--(.*?)(?=\-\-DATA\-\-|$)/s', $test, $matches, PREG_SET_ORDER); + foreach ($matches as $match) { + $output = trim($template->render(eval($match[1].';')), "\n "); + $expected = trim($match[2], "\n "); + + $this->assertEquals($expected, $output, $message); + if ($output != $expected) { + echo 'Compiled template that failed:'; + + foreach (array_keys($templates) as $name) { + $source = $loader->getSource($name); + echo $twig->compile($twig->parse($twig->tokenize($source, $name))); + } + } + } } - } } - } } class Foo { - public function bar($param1 = null, $param2 = null) - { - return 'bar'.($param1 ? '_'.$param1 : '').($param2 ? '-'.$param2 : ''); - } - - public function getFoo() - { - return 'foo'; - } - - public function getSelf() - { - return $this; - } + public function bar($param1 = null, $param2 = null) + { + return 'bar'.($param1 ? '_'.$param1 : '').($param2 ? '-'.$param2 : ''); + } + + public function getFoo() + { + return 'foo'; + } + + public function getSelf() + { + return $this; + } } class TestExtension extends Twig_Extension { - public function getFilters() - { - return array('nl2br' => new Twig_Filter_Method($this, 'nl2br')); - } - - public function nl2br($value, $sep = '
') - { - return str_replace("\n", $sep."\n", $value); - } - - public function getName() - { - return 'test'; - } + public function getFilters() + { + return array('nl2br' => new Twig_Filter_Method($this, 'nl2br')); + } + + public function nl2br($value, $sep = '
') + { + return str_replace("\n", $sep."\n", $value); + } + + public function getName() + { + return 'test'; + } }