Did a big resource cleanup, updated Twig (now using _just_ the Twig library), updated Markdown (now using MarkdownExtra).
This commit is contained in:
parent
13d9a0514b
commit
f2b0bd5da7
453 changed files with 6288 additions and 15663 deletions
10
index.php
10
index.php
|
@ -1,4 +1,7 @@
|
|||
<?php
|
||||
// ini_set('display_errors',1);
|
||||
// error_reporting(E_ALL);
|
||||
|
||||
/*
|
||||
* Pico v0.1
|
||||
*/
|
||||
|
@ -11,9 +14,10 @@ define('THEMES_DIR', ROOT_DIR .'themes/');
|
|||
define('CACHE_DIR', LIB_DIR .'cache/');
|
||||
|
||||
require('config.php');
|
||||
require(LIB_DIR .'markdown.php');
|
||||
require(LIB_DIR .'twig/lib/Twig/Autoloader.php');
|
||||
require(LIB_DIR .'pico.php');
|
||||
require(LIB_DIR .'Michelf/Markdown.php');
|
||||
require(LIB_DIR .'Michelf/MarkdownExtra.php');
|
||||
require(LIB_DIR .'Twig/Autoloader.php');
|
||||
require(LIB_DIR .'gilbitron/Pico.php');
|
||||
$pico = new Pico();
|
||||
|
||||
?>
|
BIN
lib/.DS_Store
vendored
Normal file
BIN
lib/.DS_Store
vendored
Normal file
Binary file not shown.
2805
lib/Michelf/Markdown.php
Normal file
2805
lib/Michelf/Markdown.php
Normal file
File diff suppressed because it is too large
Load diff
40
lib/Michelf/MarkdownExtra.php
Normal file
40
lib/Michelf/MarkdownExtra.php
Normal file
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
#
|
||||
# Markdown Extra - A text-to-HTML conversion tool for web writers
|
||||
#
|
||||
# PHP Markdown Extra
|
||||
# Copyright (c) 2004-2013 Michel Fortin
|
||||
# <http://michelf.com/projects/php-markdown/>
|
||||
#
|
||||
# Original Markdown
|
||||
# Copyright (c) 2004-2006 John Gruber
|
||||
# <http://daringfireball.net/projects/markdown/>
|
||||
#
|
||||
namespace Michelf;
|
||||
|
||||
|
||||
# Just force Michelf/Markdown.php to load. This is needed to load
|
||||
# the temporary implementation class. See below for details.
|
||||
\Michelf\Markdown::MARKDOWNLIB_VERSION;
|
||||
|
||||
#
|
||||
# Markdown Extra Parser Class
|
||||
#
|
||||
# Note: Currently the implementation resides in the temporary class
|
||||
# \Michelf\MarkdownExtra_TmpImpl (in the same file as \Michelf\Markdown).
|
||||
# This makes it easier to propagate the changes between the three different
|
||||
# packaging styles of PHP Markdown. Once this issue is resolved, the
|
||||
# _MarkdownExtra_TmpImpl will disappear and this one will contain the code.
|
||||
#
|
||||
|
||||
class MarkdownExtra extends \Michelf\_MarkdownExtra_TmpImpl {
|
||||
|
||||
### Parser Implementation ###
|
||||
|
||||
# Temporarily, the implemenation is in the _MarkdownExtra_TmpImpl class.
|
||||
# See note above.
|
||||
|
||||
}
|
||||
|
||||
|
||||
?>
|
|
@ -1,4 +1,8 @@
|
|||
<?php
|
||||
/**
|
||||
* use the Michelf namespaces
|
||||
*/
|
||||
use \Michelf\Markdown, \Michelf\MarkdownExtra;
|
||||
|
||||
class Pico {
|
||||
|
||||
|
@ -51,9 +55,9 @@ class Pico {
|
|||
function parse_content($content)
|
||||
{
|
||||
$content = str_replace('%base_url%', $this->base_url(), $content);
|
||||
$content = Markdown($content);
|
||||
$my_html = MarkdownExtra::defaultTransform($content);
|
||||
|
||||
return $content;
|
||||
return $my_html;
|
||||
}
|
||||
|
||||
function read_file_meta($content)
|
|
@ -1,9 +0,0 @@
|
|||
Twig is written and maintained by the Twig Team:
|
||||
|
||||
Lead Developer:
|
||||
|
||||
- Fabien Potencier <fabien.potencier@symfony-project.org>
|
||||
|
||||
Project Founder:
|
||||
|
||||
- Armin Ronacher <armin.ronacher@active-4.com>
|
11
lib/twig/lib/Twig/Autoloader.php → lib/twig/Autoloader.php
Executable file → Normal file
11
lib/twig/lib/Twig/Autoloader.php → lib/twig/Autoloader.php
Executable file → Normal file
|
@ -12,15 +12,14 @@
|
|||
/**
|
||||
* Autoloads Twig classes.
|
||||
*
|
||||
* @package twig
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class Twig_Autoloader
|
||||
{
|
||||
/**
|
||||
* Registers Twig_Autoloader as an SPL autoloader.
|
||||
*/
|
||||
static public function register()
|
||||
public static function register()
|
||||
{
|
||||
ini_set('unserialize_callback_func', 'spl_autoload_call');
|
||||
spl_autoload_register(array(new self, 'autoload'));
|
||||
|
@ -29,11 +28,9 @@ class Twig_Autoloader
|
|||
/**
|
||||
* Handles autoloading of classes.
|
||||
*
|
||||
* @param string $class A class name.
|
||||
*
|
||||
* @return boolean Returns true if the class has been loaded
|
||||
* @param string $class A class name.
|
||||
*/
|
||||
static public function autoload($class)
|
||||
public static function autoload($class)
|
||||
{
|
||||
if (0 !== strpos($class, 'Twig')) {
|
||||
return;
|
|
@ -1,474 +0,0 @@
|
|||
* 1.6.4 (2012-04-02)
|
||||
|
||||
* fixed PHP notice in Twig_Error::guessTemplateLine() introduced in 1.6.3
|
||||
* fixed performance when compiling large files
|
||||
* optimized parent template creation when the template does not use dynamic inheritance
|
||||
|
||||
* 1.6.3 (2012-03-22)
|
||||
|
||||
* fixed usage of Z_ADDREF_P for PHP 5.2 in the C extension
|
||||
* fixed compilation of numeric values used in templates when using a locale where the decimal separator is not a dot
|
||||
* made the strategy used to guess the real template file name and line number in exception messages much faster and more accurate
|
||||
|
||||
* 1.6.2 (2012-03-18)
|
||||
|
||||
* fixed sandbox mode when used with inheritance
|
||||
* added preserveKeys support for the slice filter
|
||||
* fixed the date filter when a DateTime instance is passed with a specific timezone
|
||||
* added a trim filter
|
||||
|
||||
* 1.6.1 (2012-02-29)
|
||||
|
||||
* fixed Twig C extension
|
||||
* removed the creation of Twig_Markup instances when not needed
|
||||
* added a way to set the default global timezone for dates
|
||||
* fixed the slice filter on strings when the length is not specified
|
||||
* fixed the creation of the cache directory in case of a race condition
|
||||
|
||||
* 1.6.0 (2012-02-04)
|
||||
|
||||
* fixed raw blocks when used with the whitespace trim option
|
||||
* made a speed optimization to macro calls when imported via the "from" tag
|
||||
* fixed globals, parsers, visitors, filters, tests, and functions management in Twig_Environment when a new one or new extension is added
|
||||
* fixed the attribute function when passing arguments
|
||||
* added slice notation support for the [] operator (syntactic sugar for the slice operator)
|
||||
* added a slice filter
|
||||
* added string support for the reverse filter
|
||||
* fixed the empty test and the length filter for Twig_Markup instances
|
||||
* added a date function to ease date comparison
|
||||
* fixed unary operators precedence
|
||||
* added recursive parsing support in the parser
|
||||
* added string and integer handling for the random function
|
||||
|
||||
* 1.5.1 (2012-01-05)
|
||||
|
||||
* fixed a regression when parsing strings
|
||||
|
||||
* 1.5.0 (2012-01-04)
|
||||
|
||||
* added Traversable objects support for the join filter
|
||||
|
||||
* 1.5.0-RC2 (2011-12-30)
|
||||
|
||||
* added a way to set the default global date interval format
|
||||
* fixed the date filter for DateInterval instances (setTimezone() does not exist for them)
|
||||
* refactored Twig_Template::display() to ease its extension
|
||||
* added a number_format filter
|
||||
|
||||
* 1.5.0-RC1 (2011-12-26)
|
||||
|
||||
* removed the need to quote hash keys
|
||||
* allowed hash keys to be any expression
|
||||
* added a do tag
|
||||
* added a flush tag
|
||||
* added support for dynamically named filters and functions
|
||||
* added a dump function to help debugging templates
|
||||
* added a nl2br filter
|
||||
* added a random function
|
||||
* added a way to change the default format for the date filter
|
||||
* fixed the lexer when an operator ending with a letter ends a line
|
||||
* added string interpolation support
|
||||
* enhanced exceptions for unknown filters, functions, tests, and tags
|
||||
|
||||
* 1.4.0 (2011-12-07)
|
||||
|
||||
* fixed lexer when using big numbers (> PHP_INT_MAX)
|
||||
* added missing preserveKeys argument to the reverse filter
|
||||
* fixed macros containing filter tag calls
|
||||
|
||||
* 1.4.0-RC2 (2011-11-27)
|
||||
|
||||
* removed usage of Reflection in Twig_Template::getAttribute()
|
||||
* added a C extension that can optionally replace Twig_Template::getAttribute()
|
||||
* added negative timestamp support to the date filter
|
||||
|
||||
* 1.4.0-RC1 (2011-11-20)
|
||||
|
||||
* optimized variable access when using PHP 5.4
|
||||
* changed the precedence of the .. operator to be more consistent with languages that implements such a feature like Ruby
|
||||
* added an Exception to Twig_Loader_Array::isFresh() method when the template does not exist to be consistent with other loaders
|
||||
* added Twig_Function_Node to allow more complex functions to have their own Node class
|
||||
* added Twig_Filter_Node to allow more complex filters to have their own Node class
|
||||
* added Twig_Test_Node to allow more complex tests to have their own Node class
|
||||
* added a better error message when a template is empty but contain a BOM
|
||||
* fixed "in" operator for empty strings
|
||||
* fixed the "defined" test and the "default" filter (now works with more than one call (foo.bar.foo) and for both values of the strict_variables option)
|
||||
* changed the way extensions are loaded (addFilter/addFunction/addGlobal/addTest/addNodeVisitor/addTokenParser/addExtension can now be called in any order)
|
||||
* added Twig_Environment::display()
|
||||
* made the escape filter smarter when the encoding is not supported by PHP
|
||||
* added a convert_encoding filter
|
||||
* moved all node manipulations outside the compile() Node method
|
||||
* made several speed optimizations
|
||||
|
||||
* 1.3.0 (2011-10-08)
|
||||
|
||||
no changes
|
||||
|
||||
* 1.3.0-RC1 (2011-10-04)
|
||||
|
||||
* added an optimization for the parent() function
|
||||
* added cache reloading when auto_reload is true and an extension has been modified
|
||||
* added the possibility to force the escaping of a string already marked as safe (instance of Twig_Markup)
|
||||
* allowed empty templates to be used as traits
|
||||
* added traits support for the "parent" function
|
||||
|
||||
* 1.2.0 (2011-09-13)
|
||||
|
||||
no changes
|
||||
|
||||
* 1.2.0-RC1 (2011-09-10)
|
||||
|
||||
* enhanced the exception when a tag remains unclosed
|
||||
* added support for empty Countable objects for the "empty" test
|
||||
* fixed algorithm that determines if a template using inheritance is valid (no output between block definitions)
|
||||
* added better support for encoding problems when escaping a string (available as of PHP 5.4)
|
||||
* added a way to ignore a missing template when using the "include" tag ({% include "foo" ignore missing %})
|
||||
* added support for an array of templates to the "include" and "extends" tags ({% include ['foo', 'bar'] %})
|
||||
* added support for bitwise operators in expressions
|
||||
* added the "attribute" function to allow getting dynamic attributes on variables
|
||||
* added Twig_Loader_Chain
|
||||
* added Twig_Loader_Array::setTemplate()
|
||||
* added an optimization for the set tag when used to capture a large chunk of static text
|
||||
* changed name regex to match PHP one "[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*" (works for blocks, tags, functions, filters, and macros)
|
||||
* removed the possibility to use the "extends" tag from a block
|
||||
* added "if" modifier support to "for" loops
|
||||
|
||||
* 1.1.2 (2011-07-30)
|
||||
|
||||
* fixed json_encode filter on PHP 5.2
|
||||
* fixed regression introduced in 1.1.1 ({{ block(foo|lower) }})
|
||||
* fixed inheritance when using conditional parents
|
||||
* fixed compilation of templates when the body of a child template is not empty
|
||||
* fixed output when a macro throws an exception
|
||||
* fixed a parsing problem when a large chunk of text is enclosed in a comment tag
|
||||
* added PHPDoc for all Token parsers and Core extension functions
|
||||
|
||||
* 1.1.1 (2011-07-17)
|
||||
|
||||
* added a performance optimization in the Optimizer (also helps to lower the number of nested level calls)
|
||||
* made some performance improvement for some edge cases
|
||||
|
||||
* 1.1.0 (2011-06-28)
|
||||
|
||||
* fixed json_encode filter
|
||||
|
||||
* 1.1.0-RC3 (2011-06-24)
|
||||
|
||||
* fixed method case-sensitivity when using the sandbox mode
|
||||
* added timezone support for the date filter
|
||||
* fixed possible security problems with NUL bytes
|
||||
|
||||
* 1.1.0-RC2 (2011-06-16)
|
||||
|
||||
* added an exception when the template passed to "use" is not a string
|
||||
* made 'a.b is defined' not throw an exception if a is not defined (in strict mode)
|
||||
* added {% line \d+ %} directive
|
||||
|
||||
* 1.1.0-RC1 (2011-05-28)
|
||||
|
||||
Flush your cache after upgrading.
|
||||
|
||||
* fixed date filter when using a timestamp
|
||||
* fixed the defined test for some cases
|
||||
* fixed a parsing problem when a large chunk of text is enclosed in a raw tag
|
||||
* added support for horizontal reuse of template blocks (see docs for more information)
|
||||
* added whitespace control modifier to all tags (see docs for more information)
|
||||
* added null as an alias for none (the null test is also an alias for the none test now)
|
||||
* made TRUE, FALSE, NONE equivalent to their lowercase counterparts
|
||||
* wrapped all compilation and runtime exceptions with Twig_Error_Runtime and added logic to guess the template name and line
|
||||
* moved display() method to Twig_Template (generated templates should now use doDisplay() instead)
|
||||
|
||||
* 1.0.0 (2011-03-27)
|
||||
|
||||
* fixed output when using mbstring
|
||||
* fixed duplicate call of methods when using the sandbox
|
||||
* made the charset configurable for the escape filter
|
||||
|
||||
* 1.0.0-RC2 (2011-02-21)
|
||||
|
||||
* changed the way {% set %} works when capturing (the content is now marked as safe)
|
||||
* added support for macro name in the endmacro tag
|
||||
* make Twig_Error compatible with PHP 5.3.0 >
|
||||
* fixed an infinite loop on some Windows configurations
|
||||
* fixed the "length" filter for numbers
|
||||
* fixed Template::getAttribute() as properties in PHP are case sensitive
|
||||
* removed coupling between Twig_Node and Twig_Template
|
||||
* fixed the ternary operator precedence rule
|
||||
|
||||
* 1.0.0-RC1 (2011-01-09)
|
||||
|
||||
Backward incompatibilities:
|
||||
|
||||
* the "items" filter, which has been deprecated for quite a long time now, has been removed
|
||||
* the "range" filter has been converted to a function: 0|range(10) -> range(0, 10)
|
||||
* the "constant" filter has been converted to a function: {{ some_date|date('DATE_W3C'|constant) }} -> {{ some_date|date(constant('DATE_W3C')) }}
|
||||
* the "cycle" filter has been converted to a function: {{ ['odd', 'even']|cycle(i) }} -> {{ cycle(['odd', 'even'], i) }}
|
||||
* the "for" tag does not support "joined by" anymore
|
||||
* the "autoescape" first argument is now "true"/"false" (instead of "on"/"off")
|
||||
* the "parent" tag has been replaced by a "parent" function ({{ parent() }} instead of {% parent %})
|
||||
* the "display" tag has been replaced by a "block" function ({{ block('title') }} instead of {% display title %})
|
||||
* removed the grammar and simple token parser (moved to the Twig Extensions repository)
|
||||
|
||||
Changes:
|
||||
|
||||
* added "needs_context" option for filters and functions (the context is then passed as a first argument)
|
||||
* added global variables support
|
||||
* made macros return their value instead of echoing directly (fixes calling a macro in sandbox mode)
|
||||
* added the "from" tag to import macros as functions
|
||||
* added support for functions (a function is just syntactic sugar for a getAttribute() call)
|
||||
* made macros callable when sandbox mode is enabled
|
||||
* added an exception when a macro uses a reserved name
|
||||
* the "default" filter now uses the "empty" test instead of just checking for null
|
||||
* added the "empty" test
|
||||
|
||||
* 0.9.10 (2010-12-16)
|
||||
|
||||
Backward incompatibilities:
|
||||
|
||||
* The Escaper extension is enabled by default, which means that all displayed
|
||||
variables are now automatically escaped. You can revert to the previous
|
||||
behavior by removing the extension via $env->removeExtension('escaper')
|
||||
or just set the 'autoescape' option to 'false'.
|
||||
* removed the "without loop" attribute for the "for" tag (not needed anymore
|
||||
as the Optimizer take care of that for most cases)
|
||||
* arrays and hashes have now a different syntax
|
||||
* arrays keep the same syntax with square brackets: [1, 2]
|
||||
* hashes now use curly braces (["a": "b"] should now be written as {"a": "b"})
|
||||
* support for "arrays with keys" and "hashes without keys" is not supported anymore ([1, "foo": "bar"] or {"foo": "bar", 1})
|
||||
* the i18n extension is now part of the Twig Extensions repository
|
||||
|
||||
Changes:
|
||||
|
||||
* added the merge filter
|
||||
* removed 'is_escaper' option for filters (a left over from the previous version) -- you must use 'is_safe' now instead
|
||||
* fixed usage of operators as method names (like is, in, and not)
|
||||
* changed the order of execution for node visitors
|
||||
* fixed default() filter behavior when used with strict_variables set to on
|
||||
* fixed filesystem loader compatibility with PHAR files
|
||||
* enhanced error messages when an unexpected token is parsed in an expression
|
||||
* fixed filename not being added to syntax error messages
|
||||
* added the autoescape option to enable/disable autoescaping
|
||||
* removed the newline after a comment (mimicks PHP behavior)
|
||||
* added a syntax error exception when parent block is used on a template that does not extend another one
|
||||
* made the Escaper extension enabled by default
|
||||
* fixed sandbox extension when used with auto output escaping
|
||||
* fixed escaper when wrapping a Twig_Node_Print (the original class must be preserved)
|
||||
* added an Optimizer extension (enabled by default; optimizes "for" loops and "raw" filters)
|
||||
* added priority to node visitors
|
||||
|
||||
* 0.9.9 (2010-11-28)
|
||||
|
||||
Backward incompatibilities:
|
||||
* the self special variable has been renamed to _self
|
||||
* the odd and even filters are now tests:
|
||||
{{ foo|odd }} must now be written {{ foo is odd }}
|
||||
* the "safe" filter has been renamed to "raw"
|
||||
* in Node classes,
|
||||
sub-nodes are now accessed via getNode() (instead of property access)
|
||||
attributes via getAttribute() (instead of array access)
|
||||
* the urlencode filter had been renamed to url_encode
|
||||
* the include tag now merges the passed variables with the current context by default
|
||||
(the old behavior is still possible by adding the "only" keyword)
|
||||
* moved Exceptions to Twig_Error_* (Twig_SyntaxError/Twig_RuntimeError are now Twig_Error_Syntax/Twig_Error_Runtime)
|
||||
* removed support for {{ 1 < i < 3 }} (use {{ i > 1 and i < 3 }} instead)
|
||||
* the "in" filter has been removed ({{ a|in(b) }} should now be written {{ a in b }})
|
||||
|
||||
Changes:
|
||||
* added file and line to Twig_Error_Runtime exceptions thrown from Twig_Template
|
||||
* changed trans tag to accept any variable for the plural count
|
||||
* fixed sandbox mode (__toString() method check was not enforced if called implicitly from complex statements)
|
||||
* added the ** (power) operator
|
||||
* changed the algorithm used for parsing expressions
|
||||
* added the spaceless tag
|
||||
* removed trim_blocks option
|
||||
* added support for is*() methods for attributes (foo.bar now looks for foo->getBar() or foo->isBar())
|
||||
* changed all exceptions to extend Twig_Error
|
||||
* fixed unary expressions ({{ not(1 or 0) }})
|
||||
* fixed child templates (with an extend tag) that uses one or more imports
|
||||
* added support for {{ 1 not in [2, 3] }} (more readable than the current {{ not (1 in [2, 3]) }})
|
||||
* escaping has been rewritten
|
||||
* the implementation of template inheritance has been rewritten
|
||||
(blocks can now be called individually and still work with inheritance)
|
||||
* fixed error handling for if tag when a syntax error occurs within a subparse process
|
||||
* added a way to implement custom logic for resolving token parsers given a tag name
|
||||
* fixed js escaper to be stricter (now uses a whilelist-based js escaper)
|
||||
* added the following filers: "constant", "trans", "replace", "json_encode"
|
||||
* added a "constant" test
|
||||
* fixed objects with __toString() not being autoescaped
|
||||
* fixed subscript expressions when calling __call() (methods now keep the case)
|
||||
* added "test" feature (accessible via the "is" operator)
|
||||
* removed the debug tag (should be done in an extension)
|
||||
* fixed trans tag when no vars are used in plural form
|
||||
* fixed race condition when writing template cache
|
||||
* added the special _charset variable to reference the current charset
|
||||
* added the special _context variable to reference the current context
|
||||
* renamed self to _self (to avoid conflict)
|
||||
* fixed Twig_Template::getAttribute() for protected properties
|
||||
|
||||
* 0.9.8 (2010-06-28)
|
||||
|
||||
Backward incompatibilities:
|
||||
* the trans tag plural count is now attached to the plural tag:
|
||||
old: `{% trans count %}...{% plural %}...{% endtrans %}`
|
||||
new: `{% trans %}...{% plural count %}...{% endtrans %}`
|
||||
|
||||
* added a way to translate strings coming from a variable ({% trans var %})
|
||||
* fixed trans tag when used with the Escaper extension
|
||||
* fixed default cache umask
|
||||
* removed Twig_Template instances from the debug tag output
|
||||
* fixed objects with __isset() defined
|
||||
* fixed set tag when used with a capture
|
||||
* fixed type hinting for Twig_Environment::addFilter() method
|
||||
|
||||
* 0.9.7 (2010-06-12)
|
||||
|
||||
Backward incompatibilities:
|
||||
* changed 'as' to '=' for the set tag ({% set title as "Title" %} must now be {% set title = "Title" %})
|
||||
* removed the sandboxed attribute of the include tag (use the new sandbox tag instead)
|
||||
* refactored the Node system (if you have custom nodes, you will have to update them to use the new API)
|
||||
|
||||
* added self as a special variable that refers to the current template (useful for importing macros from the current template)
|
||||
* added Twig_Template instance support to the include tag
|
||||
* added support for dynamic and conditional inheritance ({% extends some_var %} and {% extends standalone ? "minimum" : "base" %})
|
||||
* added a grammar sub-framework to ease the creation of custom tags
|
||||
* fixed the for tag for large arrays (some loop variables are now only available for arrays and objects that implement the Countable interface)
|
||||
* removed the Twig_Resource::resolveMissingFilter() method
|
||||
* fixed the filter tag which did not apply filtering to included files
|
||||
* added a bunch of unit tests
|
||||
* added a bunch of phpdoc
|
||||
* added a sandbox tag in the sandbox extension
|
||||
* changed the date filter to support any date format supported by DateTime
|
||||
* added strict_variable setting to throw an exception when an invalid variable is used in a template (disabled by default)
|
||||
* added the lexer, parser, and compiler as arguments to the Twig_Environment constructor
|
||||
* changed the cache option to only accepts an explicit path to a cache directory or false
|
||||
* added a way to add token parsers, filters, and visitors without creating an extension
|
||||
* added three interfaces: Twig_NodeInterface, Twig_TokenParserInterface, and Twig_FilterInterface
|
||||
* changed the generated code to match the new coding standards
|
||||
* fixed sandbox mode (__toString() method check was not enforced if called implicitly from a simple statement like {{ article }})
|
||||
* added an exception when a child template has a non-empty body (as it is always ignored when rendering)
|
||||
|
||||
* 0.9.6 (2010-05-12)
|
||||
|
||||
* fixed variables defined outside a loop and for which the value changes in a for loop
|
||||
* fixed the test suite for PHP 5.2 and older versions of PHPUnit
|
||||
* added support for __call() in expression resolution
|
||||
* fixed node visiting for macros (macros are now visited by visitors as any other node)
|
||||
* fixed nested block definitions with a parent call (rarely useful but nonetheless supported now)
|
||||
* added the cycle filter
|
||||
* fixed the Lexer when mbstring.func_overload is used with an mbstring.internal_encoding different from ASCII
|
||||
* added a long-syntax for the set tag ({% set foo %}...{% endset %})
|
||||
* unit tests are now powered by PHPUnit
|
||||
* added support for gettext via the `i18n` extension
|
||||
* fixed twig_capitalize_string_filter() and fixed twig_length_filter() when used with UTF-8 values
|
||||
* added a more useful exception if an if tag is not closed properly
|
||||
* added support for escaping strategy in the autoescape tag
|
||||
* fixed lexer when a template has a big chunk of text between/in a block
|
||||
|
||||
* 0.9.5 (2010-01-20)
|
||||
|
||||
As for any new release, don't forget to remove all cached templates after
|
||||
upgrading.
|
||||
|
||||
If you have defined custom filters, you MUST upgrade them for this release. To
|
||||
upgrade, replace "array" with "new Twig_Filter_Function", and replace the
|
||||
environment constant by the "needs_environment" option:
|
||||
|
||||
// before
|
||||
'even' => array('twig_is_even_filter', false),
|
||||
'escape' => array('twig_escape_filter', true),
|
||||
|
||||
// after
|
||||
'even' => new Twig_Filter_Function('twig_is_even_filter'),
|
||||
'escape' => new Twig_Filter_Function('twig_escape_filter', array('needs_environment' => true)),
|
||||
|
||||
If you have created NodeTransformer classes, you will need to upgrade them to
|
||||
the new interface (please note that the interface is not yet considered
|
||||
stable).
|
||||
|
||||
* fixed list nodes that did not extend the Twig_NodeListInterface
|
||||
* added the "without loop" option to the for tag (it disables the generation of the loop variable)
|
||||
* refactored node transformers to node visitors
|
||||
* fixed automatic-escaping for blocks
|
||||
* added a way to specify variables to pass to an included template
|
||||
* changed the automatic-escaping rules to be more sensible and more configurable in custom filters (the documentation lists all the rules)
|
||||
* improved the filter system to allow object methods to be used as filters
|
||||
* changed the Array and String loaders to actually make use of the cache mechanism
|
||||
* included the default filter function definitions in the extension class files directly (Core, Escaper)
|
||||
* added the // operator (like the floor() PHP function)
|
||||
* added the .. operator (as a syntactic sugar for the range filter when the step is 1)
|
||||
* added the in operator (as a syntactic sugar for the in filter)
|
||||
* added the following filters in the Core extension: in, range
|
||||
* added support for arrays (same behavior as in PHP, a mix between lists and dictionaries, arrays and hashes)
|
||||
* enhanced some error messages to provide better feedback in case of parsing errors
|
||||
|
||||
* 0.9.4 (2009-12-02)
|
||||
|
||||
If you have custom loaders, you MUST upgrade them for this release: The
|
||||
Twig_Loader base class has been removed, and the Twig_LoaderInterface has also
|
||||
been changed (see the source code for more information or the documentation).
|
||||
|
||||
* added support for DateTime instances for the date filter
|
||||
* fixed loop.last when the array only has one item
|
||||
* made it possible to insert newlines in tag and variable blocks
|
||||
* fixed a bug when a literal '\n' were present in a template text
|
||||
* fixed bug when the filename of a template contains */
|
||||
* refactored loaders
|
||||
|
||||
* 0.9.3 (2009-11-11)
|
||||
|
||||
This release is NOT backward compatible with the previous releases.
|
||||
|
||||
The loaders do not take the cache and autoReload arguments anymore. Instead,
|
||||
the Twig_Environment class has two new options: cache and auto_reload.
|
||||
Upgrading your code means changing this kind of code:
|
||||
|
||||
$loader = new Twig_Loader_Filesystem('/path/to/templates', '/path/to/compilation_cache', true);
|
||||
$twig = new Twig_Environment($loader);
|
||||
|
||||
to something like this:
|
||||
|
||||
$loader = new Twig_Loader_Filesystem('/path/to/templates');
|
||||
$twig = new Twig_Environment($loader, array(
|
||||
'cache' => '/path/to/compilation_cache',
|
||||
'auto_reload' => true,
|
||||
));
|
||||
|
||||
* deprecated the "items" filter as it is not needed anymore
|
||||
* made cache and auto_reload options of Twig_Environment instead of arguments of Twig_Loader
|
||||
* optimized template loading speed
|
||||
* removed output when an error occurs in a template and render() is used
|
||||
* made major speed improvements for loops (up to 300% on even the smallest loops)
|
||||
* added properties as part of the sandbox mode
|
||||
* added public properties support (obj.item can now be the item property on the obj object)
|
||||
* extended set tag to support expression as value ({% set foo as 'foo' ~ 'bar' %} )
|
||||
* fixed bug when \ was used in HTML
|
||||
|
||||
* 0.9.2 (2009-10-29)
|
||||
|
||||
* made some speed optimizations
|
||||
* changed the cache extension to .php
|
||||
* added a js escaping strategy
|
||||
* added support for short block tag
|
||||
* changed the filter tag to allow chained filters
|
||||
* made lexer more flexible as you can now change the default delimiters
|
||||
* added set tag
|
||||
* changed default directory permission when cache dir does not exist (more secure)
|
||||
* added macro support
|
||||
* changed filters first optional argument to be a Twig_Environment instance instead of a Twig_Template instance
|
||||
* made Twig_Autoloader::autoload() a static method
|
||||
* avoid writing template file if an error occurs
|
||||
* added $ escaping when outputting raw strings
|
||||
* enhanced some error messages to ease debugging
|
||||
* fixed empty cache files when the template contains an error
|
||||
|
||||
* 0.9.1 (2009-10-14)
|
||||
|
||||
* fixed a bug in PHP 5.2.6
|
||||
* fixed numbers with one than one decimal
|
||||
* added support for method calls with arguments ({{ foo.bar('a', 43) }})
|
||||
* made small speed optimizations
|
||||
* made minor tweaks to allow better extensibility and flexibility
|
||||
|
||||
* 0.9.0 (2009-10-12)
|
||||
|
||||
* Initial release
|
49
lib/twig/lib/Twig/Compiler.php → lib/twig/Compiler.php
Executable file → Normal file
49
lib/twig/lib/Twig/Compiler.php → lib/twig/Compiler.php
Executable file → Normal file
|
@ -13,8 +13,7 @@
|
|||
/**
|
||||
* Compiles a node to PHP code.
|
||||
*
|
||||
* @package twig
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class Twig_Compiler implements Twig_CompilerInterface
|
||||
{
|
||||
|
@ -25,6 +24,7 @@ class Twig_Compiler implements Twig_CompilerInterface
|
|||
protected $debugInfo;
|
||||
protected $sourceOffset;
|
||||
protected $sourceLine;
|
||||
protected $filename;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
|
@ -37,6 +37,11 @@ class Twig_Compiler implements Twig_CompilerInterface
|
|||
$this->debugInfo = array();
|
||||
}
|
||||
|
||||
public function getFilename()
|
||||
{
|
||||
return $this->filename;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the environment instance related to this compiler.
|
||||
*
|
||||
|
@ -70,9 +75,14 @@ class Twig_Compiler implements Twig_CompilerInterface
|
|||
$this->lastLine = null;
|
||||
$this->source = '';
|
||||
$this->sourceOffset = 0;
|
||||
$this->sourceLine = 0;
|
||||
// source code starts at 1 (as we then increment it when we encounter new lines)
|
||||
$this->sourceLine = 1;
|
||||
$this->indentation = $indentation;
|
||||
|
||||
if ($node instanceof Twig_Node_Module) {
|
||||
$this->filename = $node->getAttribute('filename');
|
||||
}
|
||||
|
||||
$node->compile($this);
|
||||
|
||||
return $this;
|
||||
|
@ -92,7 +102,7 @@ class Twig_Compiler implements Twig_CompilerInterface
|
|||
/**
|
||||
* Adds a raw string to the compiled code.
|
||||
*
|
||||
* @param string $string The string
|
||||
* @param string $string The string
|
||||
*
|
||||
* @return Twig_Compiler The current compiler instance
|
||||
*/
|
||||
|
@ -119,6 +129,11 @@ class Twig_Compiler implements Twig_CompilerInterface
|
|||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends an indentation to the current PHP code after compilation.
|
||||
*
|
||||
* @return Twig_Compiler The current compiler instance
|
||||
*/
|
||||
public function addIndentation()
|
||||
{
|
||||
$this->source .= str_repeat(' ', $this->indentation * 4);
|
||||
|
@ -129,7 +144,7 @@ class Twig_Compiler implements Twig_CompilerInterface
|
|||
/**
|
||||
* Adds a quoted string to the compiled code.
|
||||
*
|
||||
* @param string $value The string
|
||||
* @param string $value The string
|
||||
*
|
||||
* @return Twig_Compiler The current compiler instance
|
||||
*/
|
||||
|
@ -143,7 +158,7 @@ class Twig_Compiler implements Twig_CompilerInterface
|
|||
/**
|
||||
* Returns a PHP representation of a given value.
|
||||
*
|
||||
* @param mixed $value The value to convert
|
||||
* @param mixed $value The value to convert
|
||||
*
|
||||
* @return Twig_Compiler The current compiler instance
|
||||
*/
|
||||
|
@ -192,12 +207,21 @@ class Twig_Compiler implements Twig_CompilerInterface
|
|||
public function addDebugInfo(Twig_NodeInterface $node)
|
||||
{
|
||||
if ($node->getLine() != $this->lastLine) {
|
||||
$this->sourceLine += substr_count($this->source, "\n", $this->sourceOffset);
|
||||
$this->write("// line {$node->getLine()}\n");
|
||||
|
||||
// when mbstring.func_overload is set to 2
|
||||
// mb_substr_count() replaces substr_count()
|
||||
// but they have different signatures!
|
||||
if (((int) ini_get('mbstring.func_overload')) & 2) {
|
||||
// this is much slower than the "right" version
|
||||
$this->sourceLine += mb_substr_count(mb_substr($this->source, $this->sourceOffset), "\n");
|
||||
} else {
|
||||
$this->sourceLine += substr_count($this->source, "\n", $this->sourceOffset);
|
||||
}
|
||||
$this->sourceOffset = strlen($this->source);
|
||||
$this->debugInfo[$this->sourceLine] = $node->getLine();
|
||||
|
||||
$this->lastLine = $node->getLine();
|
||||
$this->write("// line {$node->getLine()}\n");
|
||||
}
|
||||
|
||||
return $this;
|
||||
|
@ -231,12 +255,13 @@ class Twig_Compiler implements Twig_CompilerInterface
|
|||
*/
|
||||
public function outdent($step = 1)
|
||||
{
|
||||
$this->indentation -= $step;
|
||||
|
||||
if ($this->indentation < 0) {
|
||||
throw new Twig_Error('Unable to call outdent() as the indentation would become negative');
|
||||
// can't outdent by more steps than the current indentation level
|
||||
if ($this->indentation < $step) {
|
||||
throw new LogicException('Unable to call outdent() as the indentation would become negative');
|
||||
}
|
||||
|
||||
$this->indentation -= $step;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
10
lib/twig/lib/Twig/CompilerInterface.php → lib/twig/CompilerInterface.php
Executable file → Normal file
10
lib/twig/lib/Twig/CompilerInterface.php → lib/twig/CompilerInterface.php
Executable file → Normal file
|
@ -12,24 +12,24 @@
|
|||
/**
|
||||
* Interface implemented by compiler classes.
|
||||
*
|
||||
* @package twig
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @deprecated since 1.12 (to be removed in 2.0)
|
||||
*/
|
||||
interface Twig_CompilerInterface
|
||||
{
|
||||
/**
|
||||
* Compiles a node.
|
||||
*
|
||||
* @param Twig_NodeInterface $node The node to compile
|
||||
* @param Twig_NodeInterface $node The node to compile
|
||||
*
|
||||
* @return Twig_CompilerInterface The current compiler instance
|
||||
*/
|
||||
function compile(Twig_NodeInterface $node);
|
||||
public function compile(Twig_NodeInterface $node);
|
||||
|
||||
/**
|
||||
* Gets the current PHP code after compilation.
|
||||
*
|
||||
* @return string The PHP code
|
||||
*/
|
||||
function getSource();
|
||||
public function getSource();
|
||||
}
|
399
lib/twig/lib/Twig/Environment.php → lib/twig/Environment.php
Executable file → Normal file
399
lib/twig/lib/Twig/Environment.php → lib/twig/Environment.php
Executable file → Normal file
|
@ -12,12 +12,11 @@
|
|||
/**
|
||||
* Stores the Twig configuration.
|
||||
*
|
||||
* @package twig
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class Twig_Environment
|
||||
{
|
||||
const VERSION = '1.6.4';
|
||||
const VERSION = '1.12.3-DEV';
|
||||
|
||||
protected $charset;
|
||||
protected $loader;
|
||||
|
@ -36,6 +35,7 @@ class Twig_Environment
|
|||
protected $functions;
|
||||
protected $globals;
|
||||
protected $runtimeInitialized;
|
||||
protected $extensionInitialized;
|
||||
protected $loadedTemplates;
|
||||
protected $strictVariables;
|
||||
protected $unaryOperators;
|
||||
|
@ -50,9 +50,8 @@ class Twig_Environment
|
|||
*
|
||||
* 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).
|
||||
* * debug: When set to true, it automatically set "auto_reload" to true as
|
||||
* well (default to false).
|
||||
*
|
||||
* * charset: The charset used by the templates (default to utf-8).
|
||||
*
|
||||
|
@ -60,7 +59,7 @@ class Twig_Environment
|
|||
* templates (default to Twig_Template).
|
||||
*
|
||||
* * cache: An absolute path where to store the compiled templates, or
|
||||
* false to disable compilation cache (default)
|
||||
* false to disable compilation cache (default).
|
||||
*
|
||||
* * auto_reload: Whether to reload the template is the original source changed.
|
||||
* If you don't provide the auto_reload option, it will be
|
||||
|
@ -69,14 +68,18 @@ class Twig_Environment
|
|||
* * strict_variables: Whether to ignore invalid variables in templates
|
||||
* (default to false).
|
||||
*
|
||||
* * autoescape: Whether to enable auto-escaping (default to true);
|
||||
* * autoescape: Whether to enable auto-escaping (default to html):
|
||||
* * false: disable auto-escaping
|
||||
* * true: equivalent to html
|
||||
* * html, js: set the autoescaping to one of the supported strategies
|
||||
* * PHP callback: a PHP callback that returns an escaping strategy based on the template "filename"
|
||||
*
|
||||
* * optimizations: A flag that indicates which optimizations to apply
|
||||
* (default to -1 which means that all optimizations are enabled;
|
||||
* set it to 0 to disable)
|
||||
* set it to 0 to disable).
|
||||
*
|
||||
* @param Twig_LoaderInterface $loader A Twig_LoaderInterface instance
|
||||
* @param array $options An array of options
|
||||
* @param Twig_LoaderInterface $loader A Twig_LoaderInterface instance
|
||||
* @param array $options An array of options
|
||||
*/
|
||||
public function __construct(Twig_LoaderInterface $loader = null, $options = array())
|
||||
{
|
||||
|
@ -89,7 +92,7 @@ class Twig_Environment
|
|||
'charset' => 'UTF-8',
|
||||
'base_template_class' => 'Twig_Template',
|
||||
'strict_variables' => false,
|
||||
'autoescape' => true,
|
||||
'autoescape' => 'html',
|
||||
'cache' => false,
|
||||
'auto_reload' => null,
|
||||
'optimizations' => -1,
|
||||
|
@ -99,16 +102,17 @@ class Twig_Environment
|
|||
$this->charset = $options['charset'];
|
||||
$this->baseTemplateClass = $options['base_template_class'];
|
||||
$this->autoReload = null === $options['auto_reload'] ? $this->debug : (bool) $options['auto_reload'];
|
||||
$this->extensions = array(
|
||||
'core' => new Twig_Extension_Core(),
|
||||
'escaper' => new Twig_Extension_Escaper((bool) $options['autoescape']),
|
||||
'optimizer' => new Twig_Extension_Optimizer($options['optimizations']),
|
||||
);
|
||||
$this->strictVariables = (bool) $options['strict_variables'];
|
||||
$this->runtimeInitialized = false;
|
||||
$this->setCache($options['cache']);
|
||||
$this->functionCallbacks = array();
|
||||
$this->filterCallbacks = array();
|
||||
|
||||
$this->addExtension(new Twig_Extension_Core());
|
||||
$this->addExtension(new Twig_Extension_Escaper($options['autoescape']));
|
||||
$this->addExtension(new Twig_Extension_Optimizer($options['optimizations']));
|
||||
$this->extensionInitialized = false;
|
||||
$this->staging = new Twig_Extension_Staging();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -251,13 +255,14 @@ class Twig_Environment
|
|||
/**
|
||||
* Gets the template class associated with the given string.
|
||||
*
|
||||
* @param string $name The name for which to calculate the template class name
|
||||
* @param string $name The name for which to calculate the template class name
|
||||
* @param integer $index The index if it is an embedded template
|
||||
*
|
||||
* @return string The template class name
|
||||
*/
|
||||
public function getTemplateClass($name)
|
||||
public function getTemplateClass($name, $index = null)
|
||||
{
|
||||
return $this->templateClassPrefix.md5($this->loader->getCacheKey($name));
|
||||
return $this->templateClassPrefix.md5($this->getLoader()->getCacheKey($name)).(null === $index ? '' : '_'.$index);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -297,13 +302,14 @@ class Twig_Environment
|
|||
/**
|
||||
* Loads a template by name.
|
||||
*
|
||||
* @param string $name The template name
|
||||
* @param string $name The template name
|
||||
* @param integer $index The index if it is an embedded template
|
||||
*
|
||||
* @return Twig_TemplateInterface A template instance representing the given template name
|
||||
*/
|
||||
public function loadTemplate($name)
|
||||
public function loadTemplate($name, $index = null)
|
||||
{
|
||||
$cls = $this->getTemplateClass($name);
|
||||
$cls = $this->getTemplateClass($name, $index);
|
||||
|
||||
if (isset($this->loadedTemplates[$cls])) {
|
||||
return $this->loadedTemplates[$cls];
|
||||
|
@ -311,10 +317,10 @@ class Twig_Environment
|
|||
|
||||
if (!class_exists($cls, false)) {
|
||||
if (false === $cache = $this->getCacheFilename($name)) {
|
||||
eval('?>'.$this->compileSource($this->loader->getSource($name), $name));
|
||||
eval('?>'.$this->compileSource($this->getLoader()->getSource($name), $name));
|
||||
} else {
|
||||
if (!is_file($cache) || ($this->isAutoReload() && !$this->isTemplateFresh($name, filemtime($cache)))) {
|
||||
$this->writeCacheFile($cache, $this->compileSource($this->loader->getSource($name), $name));
|
||||
$this->writeCacheFile($cache, $this->compileSource($this->getLoader()->getSource($name), $name));
|
||||
}
|
||||
|
||||
require_once $cache;
|
||||
|
@ -349,7 +355,7 @@ class Twig_Environment
|
|||
}
|
||||
}
|
||||
|
||||
return $this->loader->isFresh($name, $time);
|
||||
return $this->getLoader()->isFresh($name, $time);
|
||||
}
|
||||
|
||||
public function resolveTemplate($names)
|
||||
|
@ -546,6 +552,10 @@ class Twig_Environment
|
|||
*/
|
||||
public function getLoader()
|
||||
{
|
||||
if (null === $this->loader) {
|
||||
throw new LogicException('You must set a loader first.');
|
||||
}
|
||||
|
||||
return $this->loader;
|
||||
}
|
||||
|
||||
|
@ -616,29 +626,29 @@ class Twig_Environment
|
|||
*/
|
||||
public function addExtension(Twig_ExtensionInterface $extension)
|
||||
{
|
||||
if ($this->extensionInitialized) {
|
||||
throw new LogicException(sprintf('Unable to register extension "%s" as extensions have already been initialized.', $extension->getName()));
|
||||
}
|
||||
|
||||
$this->extensions[$extension->getName()] = $extension;
|
||||
$this->parsers = null;
|
||||
$this->visitors = null;
|
||||
$this->filters = null;
|
||||
$this->tests = null;
|
||||
$this->functions = null;
|
||||
$this->globals = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an extension by name.
|
||||
*
|
||||
* This method is deprecated and you should not use it.
|
||||
*
|
||||
* @param string $name The extension name
|
||||
*
|
||||
* @deprecated since 1.12 (to be removed in 2.0)
|
||||
*/
|
||||
public function removeExtension($name)
|
||||
{
|
||||
if ($this->extensionInitialized) {
|
||||
throw new LogicException(sprintf('Unable to remove extension "%s" as extensions have already been initialized.', $name));
|
||||
}
|
||||
|
||||
unset($this->extensions[$name]);
|
||||
$this->parsers = null;
|
||||
$this->visitors = null;
|
||||
$this->filters = null;
|
||||
$this->tests = null;
|
||||
$this->functions = null;
|
||||
$this->globals = null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -670,8 +680,11 @@ class Twig_Environment
|
|||
*/
|
||||
public function addTokenParser(Twig_TokenParserInterface $parser)
|
||||
{
|
||||
$this->staging['token_parsers'][] = $parser;
|
||||
$this->parsers = null;
|
||||
if ($this->extensionInitialized) {
|
||||
throw new LogicException('Unable to add a token parser as extensions have already been initialized.');
|
||||
}
|
||||
|
||||
$this->staging->addTokenParser($parser);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -681,27 +694,8 @@ class Twig_Environment
|
|||
*/
|
||||
public function getTokenParsers()
|
||||
{
|
||||
if (null === $this->parsers) {
|
||||
$this->parsers = new Twig_TokenParserBroker();
|
||||
|
||||
if (isset($this->staging['token_parsers'])) {
|
||||
foreach ($this->staging['token_parsers'] as $parser) {
|
||||
$this->parsers->addTokenParser($parser);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->getExtensions() as $extension) {
|
||||
$parsers = $extension->getTokenParsers();
|
||||
foreach($parsers as $parser) {
|
||||
if ($parser instanceof Twig_TokenParserInterface) {
|
||||
$this->parsers->addTokenParser($parser);
|
||||
} elseif ($parser instanceof Twig_TokenParserBrokerInterface) {
|
||||
$this->parsers->addTokenParserBroker($parser);
|
||||
} else {
|
||||
throw new Twig_Error_Runtime('getTokenParsers() must return an array of Twig_TokenParserInterface or Twig_TokenParserBrokerInterface instances');
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!$this->extensionInitialized) {
|
||||
$this->initExtensions();
|
||||
}
|
||||
|
||||
return $this->parsers;
|
||||
|
@ -733,8 +727,11 @@ class Twig_Environment
|
|||
*/
|
||||
public function addNodeVisitor(Twig_NodeVisitorInterface $visitor)
|
||||
{
|
||||
$this->staging['visitors'][] = $visitor;
|
||||
$this->visitors = null;
|
||||
if ($this->extensionInitialized) {
|
||||
throw new LogicException('Unable to add a node visitor as extensions have already been initialized.', $extension->getName());
|
||||
}
|
||||
|
||||
$this->staging->addNodeVisitor($visitor);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -744,11 +741,8 @@ class Twig_Environment
|
|||
*/
|
||||
public function getNodeVisitors()
|
||||
{
|
||||
if (null === $this->visitors) {
|
||||
$this->visitors = isset($this->staging['visitors']) ? $this->staging['visitors'] : array();
|
||||
foreach ($this->getExtensions() as $extension) {
|
||||
$this->visitors = array_merge($this->visitors, $extension->getNodeVisitors());
|
||||
}
|
||||
if (!$this->extensionInitialized) {
|
||||
$this->initExtensions();
|
||||
}
|
||||
|
||||
return $this->visitors;
|
||||
|
@ -757,13 +751,25 @@ class Twig_Environment
|
|||
/**
|
||||
* Registers a Filter.
|
||||
*
|
||||
* @param string $name The filter name
|
||||
* @param Twig_FilterInterface $filter A Twig_FilterInterface instance
|
||||
* @param string|Twig_SimpleFilter $name The filter name or a Twig_SimpleFilter instance
|
||||
* @param Twig_FilterInterface|Twig_SimpleFilter $filter A Twig_FilterInterface instance or a Twig_SimpleFilter instance
|
||||
*/
|
||||
public function addFilter($name, Twig_FilterInterface $filter)
|
||||
public function addFilter($name, $filter = null)
|
||||
{
|
||||
$this->staging['filters'][$name] = $filter;
|
||||
$this->filters = null;
|
||||
if ($this->extensionInitialized) {
|
||||
throw new LogicException(sprintf('Unable to add filter "%s" as extensions have already been initialized.', $name));
|
||||
}
|
||||
|
||||
if (!$name instanceof Twig_SimpleFilter && !($filter instanceof Twig_SimpleFilter || $filter instanceof Twig_FilterInterface)) {
|
||||
throw new LogicException('A filter must be an instance of Twig_FilterInterface or Twig_SimpleFilter');
|
||||
}
|
||||
|
||||
if ($name instanceof Twig_SimpleFilter) {
|
||||
$filter = $name;
|
||||
$name = $filter->getName();
|
||||
}
|
||||
|
||||
$this->staging->addFilter($name, $filter);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -774,12 +780,12 @@ class Twig_Environment
|
|||
*
|
||||
* @param string $name The filter name
|
||||
*
|
||||
* @return Twig_Filter|false A Twig_Filter instance or false if the filter does not exists
|
||||
* @return Twig_Filter|false A Twig_Filter instance or false if the filter does not exist
|
||||
*/
|
||||
public function getFilter($name)
|
||||
{
|
||||
if (null === $this->filters) {
|
||||
$this->getFilters();
|
||||
if (!$this->extensionInitialized) {
|
||||
$this->initExtensions();
|
||||
}
|
||||
|
||||
if (isset($this->filters[$name])) {
|
||||
|
@ -824,11 +830,8 @@ class Twig_Environment
|
|||
*/
|
||||
public function getFilters()
|
||||
{
|
||||
if (null === $this->filters) {
|
||||
$this->filters = isset($this->staging['filters']) ? $this->staging['filters'] : array();
|
||||
foreach ($this->getExtensions() as $extension) {
|
||||
$this->filters = array_merge($this->filters, $extension->getFilters());
|
||||
}
|
||||
if (!$this->extensionInitialized) {
|
||||
$this->initExtensions();
|
||||
}
|
||||
|
||||
return $this->filters;
|
||||
|
@ -837,13 +840,25 @@ class Twig_Environment
|
|||
/**
|
||||
* Registers a Test.
|
||||
*
|
||||
* @param string $name The test name
|
||||
* @param Twig_TestInterface $test A Twig_TestInterface instance
|
||||
* @param string|Twig_SimpleTest $name The test name or a Twig_SimpleTest instance
|
||||
* @param Twig_TestInterface|Twig_SimpleTest $test A Twig_TestInterface instance or a Twig_SimpleTest instance
|
||||
*/
|
||||
public function addTest($name, Twig_TestInterface $test)
|
||||
public function addTest($name, $test = null)
|
||||
{
|
||||
$this->staging['tests'][$name] = $test;
|
||||
$this->tests = null;
|
||||
if ($this->extensionInitialized) {
|
||||
throw new LogicException(sprintf('Unable to add test "%s" as extensions have already been initialized.', $name));
|
||||
}
|
||||
|
||||
if (!$name instanceof Twig_SimpleTest && !($test instanceof Twig_SimpleTest || $test instanceof Twig_TestInterface)) {
|
||||
throw new LogicException('A test must be an instance of Twig_TestInterface or Twig_SimpleTest');
|
||||
}
|
||||
|
||||
if ($name instanceof Twig_SimpleTest) {
|
||||
$test = $name;
|
||||
$name = $test->getName();
|
||||
}
|
||||
|
||||
$this->staging->addTest($name, $test);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -853,26 +868,55 @@ class Twig_Environment
|
|||
*/
|
||||
public function getTests()
|
||||
{
|
||||
if (null === $this->tests) {
|
||||
$this->tests = isset($this->staging['tests']) ? $this->staging['tests'] : array();
|
||||
foreach ($this->getExtensions() as $extension) {
|
||||
$this->tests = array_merge($this->tests, $extension->getTests());
|
||||
}
|
||||
if (!$this->extensionInitialized) {
|
||||
$this->initExtensions();
|
||||
}
|
||||
|
||||
return $this->tests;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a test by name.
|
||||
*
|
||||
* @param string $name The test name
|
||||
*
|
||||
* @return Twig_Test|false A Twig_Test instance or false if the test does not exist
|
||||
*/
|
||||
public function getTest($name)
|
||||
{
|
||||
if (!$this->extensionInitialized) {
|
||||
$this->initExtensions();
|
||||
}
|
||||
|
||||
if (isset($this->tests[$name])) {
|
||||
return $this->tests[$name];
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a Function.
|
||||
*
|
||||
* @param string $name The function name
|
||||
* @param Twig_FunctionInterface $function A Twig_FunctionInterface instance
|
||||
* @param string|Twig_SimpleFunction $name The function name or a Twig_SimpleFunction instance
|
||||
* @param Twig_FunctionInterface|Twig_SimpleFunction $function A Twig_FunctionInterface instance or a Twig_SimpleFunction instance
|
||||
*/
|
||||
public function addFunction($name, Twig_FunctionInterface $function)
|
||||
public function addFunction($name, $function = null)
|
||||
{
|
||||
$this->staging['functions'][$name] = $function;
|
||||
$this->functions = null;
|
||||
if ($this->extensionInitialized) {
|
||||
throw new LogicException(sprintf('Unable to add function "%s" as extensions have already been initialized.', $name));
|
||||
}
|
||||
|
||||
if (!$name instanceof Twig_SimpleFunction && !($function instanceof Twig_SimpleFunction || $function instanceof Twig_FunctionInterface)) {
|
||||
throw new LogicException('A function must be an instance of Twig_FunctionInterface or Twig_SimpleFunction');
|
||||
}
|
||||
|
||||
if ($name instanceof Twig_SimpleFunction) {
|
||||
$function = $name;
|
||||
$name = $function->getName();
|
||||
}
|
||||
|
||||
$this->staging->addFunction($name, $function);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -883,12 +927,12 @@ class Twig_Environment
|
|||
*
|
||||
* @param string $name function name
|
||||
*
|
||||
* @return Twig_Function|false A Twig_Function instance or false if the function does not exists
|
||||
* @return Twig_Function|false A Twig_Function instance or false if the function does not exist
|
||||
*/
|
||||
public function getFunction($name)
|
||||
{
|
||||
if (null === $this->functions) {
|
||||
$this->getFunctions();
|
||||
if (!$this->extensionInitialized) {
|
||||
$this->initExtensions();
|
||||
}
|
||||
|
||||
if (isset($this->functions[$name])) {
|
||||
|
@ -933,11 +977,8 @@ class Twig_Environment
|
|||
*/
|
||||
public function getFunctions()
|
||||
{
|
||||
if (null === $this->functions) {
|
||||
$this->functions = isset($this->staging['functions']) ? $this->staging['functions'] : array();
|
||||
foreach ($this->getExtensions() as $extension) {
|
||||
$this->functions = array_merge($this->functions, $extension->getFunctions());
|
||||
}
|
||||
if (!$this->extensionInitialized) {
|
||||
$this->initExtensions();
|
||||
}
|
||||
|
||||
return $this->functions;
|
||||
|
@ -946,13 +987,32 @@ class Twig_Environment
|
|||
/**
|
||||
* Registers a Global.
|
||||
*
|
||||
* New globals can be added before compiling or rendering a template;
|
||||
* but after, you can only update existing globals.
|
||||
*
|
||||
* @param string $name The global name
|
||||
* @param mixed $value The global value
|
||||
*/
|
||||
public function addGlobal($name, $value)
|
||||
{
|
||||
$this->staging['globals'][$name] = $value;
|
||||
$this->globals = null;
|
||||
if ($this->extensionInitialized || $this->runtimeInitialized) {
|
||||
if (null === $this->globals) {
|
||||
$this->globals = $this->initGlobals();
|
||||
}
|
||||
|
||||
/* This condition must be uncommented in Twig 2.0
|
||||
if (!array_key_exists($name, $this->globals)) {
|
||||
throw new LogicException(sprintf('Unable to add global "%s" as the runtime or the extensions have already been initialized.', $name));
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
if ($this->extensionInitialized || $this->runtimeInitialized) {
|
||||
// update the value
|
||||
$this->globals[$name] = $value;
|
||||
} else {
|
||||
$this->staging->addGlobal($name, $value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -962,16 +1022,37 @@ class Twig_Environment
|
|||
*/
|
||||
public function getGlobals()
|
||||
{
|
||||
if (!$this->runtimeInitialized && !$this->extensionInitialized) {
|
||||
return $this->initGlobals();
|
||||
}
|
||||
|
||||
if (null === $this->globals) {
|
||||
$this->globals = isset($this->staging['globals']) ? $this->staging['globals'] : array();
|
||||
foreach ($this->getExtensions() as $extension) {
|
||||
$this->globals = array_merge($this->globals, $extension->getGlobals());
|
||||
}
|
||||
$this->globals = $this->initGlobals();
|
||||
}
|
||||
|
||||
return $this->globals;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges a context with the defined globals.
|
||||
*
|
||||
* @param array $context An array representing the context
|
||||
*
|
||||
* @return array The context merged with the globals
|
||||
*/
|
||||
public function mergeGlobals(array $context)
|
||||
{
|
||||
// we don't use array_merge as the context being generally
|
||||
// bigger than globals, this code is faster.
|
||||
foreach ($this->getGlobals() as $key => $value) {
|
||||
if (!array_key_exists($key, $context)) {
|
||||
$context[$key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return $context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the registered unary Operators.
|
||||
*
|
||||
|
@ -979,8 +1060,8 @@ class Twig_Environment
|
|||
*/
|
||||
public function getUnaryOperators()
|
||||
{
|
||||
if (null === $this->unaryOperators) {
|
||||
$this->initOperators();
|
||||
if (!$this->extensionInitialized) {
|
||||
$this->initExtensions();
|
||||
}
|
||||
|
||||
return $this->unaryOperators;
|
||||
|
@ -993,8 +1074,8 @@ class Twig_Environment
|
|||
*/
|
||||
public function getBinaryOperators()
|
||||
{
|
||||
if (null === $this->binaryOperators) {
|
||||
$this->initOperators();
|
||||
if (!$this->extensionInitialized) {
|
||||
$this->initExtensions();
|
||||
}
|
||||
|
||||
return $this->binaryOperators;
|
||||
|
@ -1014,17 +1095,93 @@ class Twig_Environment
|
|||
return array_keys($alternatives);
|
||||
}
|
||||
|
||||
protected function initOperators()
|
||||
protected function initGlobals()
|
||||
{
|
||||
$globals = array();
|
||||
foreach ($this->extensions as $extension) {
|
||||
$globals = array_merge($globals, $extension->getGlobals());
|
||||
}
|
||||
|
||||
return array_merge($globals, $this->staging->getGlobals());
|
||||
}
|
||||
|
||||
protected function initExtensions()
|
||||
{
|
||||
if ($this->extensionInitialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->extensionInitialized = true;
|
||||
$this->parsers = new Twig_TokenParserBroker();
|
||||
$this->filters = array();
|
||||
$this->functions = array();
|
||||
$this->tests = array();
|
||||
$this->visitors = array();
|
||||
$this->unaryOperators = array();
|
||||
$this->binaryOperators = array();
|
||||
foreach ($this->getExtensions() as $extension) {
|
||||
$operators = $extension->getOperators();
|
||||
|
||||
if (!$operators) {
|
||||
continue;
|
||||
foreach ($this->extensions as $extension) {
|
||||
$this->initExtension($extension);
|
||||
}
|
||||
$this->initExtension($this->staging);
|
||||
}
|
||||
|
||||
protected function initExtension(Twig_ExtensionInterface $extension)
|
||||
{
|
||||
// filters
|
||||
foreach ($extension->getFilters() as $name => $filter) {
|
||||
if ($name instanceof Twig_SimpleFilter) {
|
||||
$filter = $name;
|
||||
$name = $filter->getName();
|
||||
} elseif ($filter instanceof Twig_SimpleFilter) {
|
||||
$name = $filter->getName();
|
||||
}
|
||||
|
||||
$this->filters[$name] = $filter;
|
||||
}
|
||||
|
||||
// functions
|
||||
foreach ($extension->getFunctions() as $name => $function) {
|
||||
if ($name instanceof Twig_SimpleFunction) {
|
||||
$function = $name;
|
||||
$name = $function->getName();
|
||||
} elseif ($function instanceof Twig_SimpleFunction) {
|
||||
$name = $function->getName();
|
||||
}
|
||||
|
||||
$this->functions[$name] = $function;
|
||||
}
|
||||
|
||||
// tests
|
||||
foreach ($extension->getTests() as $name => $test) {
|
||||
if ($name instanceof Twig_SimpleTest) {
|
||||
$test = $name;
|
||||
$name = $test->getName();
|
||||
} elseif ($test instanceof Twig_SimpleTest) {
|
||||
$name = $test->getName();
|
||||
}
|
||||
|
||||
$this->tests[$name] = $test;
|
||||
}
|
||||
|
||||
// token parsers
|
||||
foreach ($extension->getTokenParsers() as $parser) {
|
||||
if ($parser instanceof Twig_TokenParserInterface) {
|
||||
$this->parsers->addTokenParser($parser);
|
||||
} elseif ($parser instanceof Twig_TokenParserBrokerInterface) {
|
||||
$this->parsers->addTokenParserBroker($parser);
|
||||
} else {
|
||||
throw new LogicException('getTokenParsers() must return an array of Twig_TokenParserInterface or Twig_TokenParserBrokerInterface instances');
|
||||
}
|
||||
}
|
||||
|
||||
// node visitors
|
||||
foreach ($extension->getNodeVisitors() as $visitor) {
|
||||
$this->visitors[] = $visitor;
|
||||
}
|
||||
|
||||
// operators
|
||||
if ($operators = $extension->getOperators()) {
|
||||
if (2 !== count($operators)) {
|
||||
throw new InvalidArgumentException(sprintf('"%s::getOperators()" does not return a valid operators array.', get_class($extension)));
|
||||
}
|
||||
|
@ -1049,12 +1206,12 @@ class Twig_Environment
|
|||
if (false !== @file_put_contents($tmpFile, $content)) {
|
||||
// rename does not work on Win32 before 5.2.6
|
||||
if (@rename($tmpFile, $file) || (@copy($tmpFile, $file) && unlink($tmpFile))) {
|
||||
chmod($file, 0644);
|
||||
@chmod($file, 0666 & ~umask());
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
throw new Twig_Error_Runtime(sprintf('Failed to write cache file "%s".', $file));
|
||||
throw new RuntimeException(sprintf('Failed to write cache file "%s".', $file));
|
||||
}
|
||||
}
|
232
lib/twig/Error.php
Normal file
232
lib/twig/Error.php
Normal file
|
@ -0,0 +1,232 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2009 Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Twig base exception.
|
||||
*
|
||||
* This exception class and its children must only be used when
|
||||
* an error occurs during the loading of a template, when a syntax error
|
||||
* is detected in a template, or when rendering a template. Other
|
||||
* errors must use regular PHP exception classes (like when the template
|
||||
* cache directory is not writable for instance).
|
||||
*
|
||||
* To help debugging template issues, this class tracks the original template
|
||||
* name and line where the error occurred.
|
||||
*
|
||||
* Whenever possible, you must set these information (original template name
|
||||
* and line number) yourself by passing them to the constructor. If some or all
|
||||
* these information are not available from where you throw the exception, then
|
||||
* this class will guess them automatically (when the line number is set to -1
|
||||
* and/or the filename is set to null). As this is a costly operation, this
|
||||
* can be disabled by passing false for both the filename and the line number
|
||||
* when creating a new instance of this class.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class Twig_Error extends Exception
|
||||
{
|
||||
protected $lineno;
|
||||
protected $filename;
|
||||
protected $rawMessage;
|
||||
protected $previous;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* Set both the line number and the filename to false to
|
||||
* disable automatic guessing of the original template name
|
||||
* and line number.
|
||||
*
|
||||
* Set the line number to -1 to enable its automatic guessing.
|
||||
* Set the filename to null to enable its automatic guessing.
|
||||
*
|
||||
* By default, automatic guessing is enabled.
|
||||
*
|
||||
* @param string $message The error message
|
||||
* @param integer $lineno The template line where the error occurred
|
||||
* @param string $filename The template file name where the error occurred
|
||||
* @param Exception $previous The previous exception
|
||||
*/
|
||||
public function __construct($message, $lineno = -1, $filename = null, Exception $previous = null)
|
||||
{
|
||||
if (version_compare(PHP_VERSION, '5.3.0', '<')) {
|
||||
$this->previous = $previous;
|
||||
parent::__construct('');
|
||||
} else {
|
||||
parent::__construct('', 0, $previous);
|
||||
}
|
||||
|
||||
$this->lineno = $lineno;
|
||||
$this->filename = $filename;
|
||||
|
||||
if (-1 === $this->lineno || null === $this->filename) {
|
||||
$this->guessTemplateInfo();
|
||||
}
|
||||
|
||||
$this->rawMessage = $message;
|
||||
|
||||
$this->updateRepr();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the raw message.
|
||||
*
|
||||
* @return string The raw message
|
||||
*/
|
||||
public function getRawMessage()
|
||||
{
|
||||
return $this->rawMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the filename where the error occurred.
|
||||
*
|
||||
* @return string The filename
|
||||
*/
|
||||
public function getTemplateFile()
|
||||
{
|
||||
return $this->filename;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the filename where the error occurred.
|
||||
*
|
||||
* @param string $filename The filename
|
||||
*/
|
||||
public function setTemplateFile($filename)
|
||||
{
|
||||
$this->filename = $filename;
|
||||
|
||||
$this->updateRepr();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the template line where the error occurred.
|
||||
*
|
||||
* @return integer The template line
|
||||
*/
|
||||
public function getTemplateLine()
|
||||
{
|
||||
return $this->lineno;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the template line where the error occurred.
|
||||
*
|
||||
* @param integer $lineno The template line
|
||||
*/
|
||||
public function setTemplateLine($lineno)
|
||||
{
|
||||
$this->lineno = $lineno;
|
||||
|
||||
$this->updateRepr();
|
||||
}
|
||||
|
||||
public function guess()
|
||||
{
|
||||
$this->guessTemplateInfo();
|
||||
$this->updateRepr();
|
||||
}
|
||||
|
||||
/**
|
||||
* For PHP < 5.3.0, provides access to the getPrevious() method.
|
||||
*
|
||||
* @param string $method The method name
|
||||
* @param array $arguments The parameters to be passed to the method
|
||||
*
|
||||
* @return Exception The previous exception or null
|
||||
*
|
||||
* @throws BadMethodCallException
|
||||
*/
|
||||
public function __call($method, $arguments)
|
||||
{
|
||||
if ('getprevious' == strtolower($method)) {
|
||||
return $this->previous;
|
||||
}
|
||||
|
||||
throw new BadMethodCallException(sprintf('Method "Twig_Error::%s()" does not exist.', $method));
|
||||
}
|
||||
|
||||
protected function updateRepr()
|
||||
{
|
||||
$this->message = $this->rawMessage;
|
||||
|
||||
$dot = false;
|
||||
if ('.' === substr($this->message, -1)) {
|
||||
$this->message = substr($this->message, 0, -1);
|
||||
$dot = true;
|
||||
}
|
||||
|
||||
if ($this->filename) {
|
||||
if (is_string($this->filename) || (is_object($this->filename) && method_exists($this->filename, '__toString'))) {
|
||||
$filename = sprintf('"%s"', $this->filename);
|
||||
} else {
|
||||
$filename = json_encode($this->filename);
|
||||
}
|
||||
$this->message .= sprintf(' in %s', $filename);
|
||||
}
|
||||
|
||||
if ($this->lineno && $this->lineno >= 0) {
|
||||
$this->message .= sprintf(' at line %d', $this->lineno);
|
||||
}
|
||||
|
||||
if ($dot) {
|
||||
$this->message .= '.';
|
||||
}
|
||||
}
|
||||
|
||||
protected function guessTemplateInfo()
|
||||
{
|
||||
$template = null;
|
||||
foreach (debug_backtrace() as $trace) {
|
||||
if (isset($trace['object']) && $trace['object'] instanceof Twig_Template && 'Twig_Template' !== get_class($trace['object'])) {
|
||||
if (null === $this->filename || $this->filename == $trace['object']->getTemplateName()) {
|
||||
$template = $trace['object'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// update template filename
|
||||
if (null !== $template && null === $this->filename) {
|
||||
$this->filename = $template->getTemplateName();
|
||||
}
|
||||
|
||||
if (null === $template || $this->lineno > -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
$r = new ReflectionObject($template);
|
||||
$file = $r->getFileName();
|
||||
|
||||
$exceptions = array($e = $this);
|
||||
while (($e instanceof self || method_exists($e, 'getPrevious')) && $e = $e->getPrevious()) {
|
||||
$exceptions[] = $e;
|
||||
}
|
||||
|
||||
while ($e = array_pop($exceptions)) {
|
||||
$traces = $e->getTrace();
|
||||
while ($trace = array_shift($traces)) {
|
||||
if (!isset($trace['file']) || !isset($trace['line']) || $file != $trace['file']) {
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($template->getDebugInfo() as $codeLine => $templateLine) {
|
||||
if ($codeLine <= $trace['line']) {
|
||||
// update template line
|
||||
$this->lineno = $templateLine;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
31
lib/twig/Error/Loader.php
Normal file
31
lib/twig/Error/Loader.php
Normal file
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2010 Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Exception thrown when an error occurs during template loading.
|
||||
*
|
||||
* Automatic template information guessing is always turned off as
|
||||
* if a template cannot be loaded, there is nothing to guess.
|
||||
* However, when a template is loaded from another one, then, we need
|
||||
* to find the current context and this is automatically done by
|
||||
* Twig_Template::displayWithErrorHandling().
|
||||
*
|
||||
* This strategy makes Twig_Environment::resolveTemplate() much faster.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class Twig_Error_Loader extends Twig_Error
|
||||
{
|
||||
public function __construct($message, $lineno = -1, $filename = null, Exception $previous = null)
|
||||
{
|
||||
parent::__construct($message, false, false, $previous);
|
||||
}
|
||||
}
|
3
lib/twig/lib/Twig/Error/Runtime.php → lib/twig/Error/Runtime.php
Executable file → Normal file
3
lib/twig/lib/Twig/Error/Runtime.php → lib/twig/Error/Runtime.php
Executable file → Normal file
|
@ -13,8 +13,7 @@
|
|||
/**
|
||||
* Exception thrown when an error occurs at runtime.
|
||||
*
|
||||
* @package twig
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class Twig_Error_Runtime extends Twig_Error
|
||||
{
|
3
lib/twig/lib/Twig/Error/Syntax.php → lib/twig/Error/Syntax.php
Executable file → Normal file
3
lib/twig/lib/Twig/Error/Syntax.php → lib/twig/Error/Syntax.php
Executable file → Normal file
|
@ -13,8 +13,7 @@
|
|||
/**
|
||||
* Exception thrown when a syntax error occurs during lexing or parsing of a template.
|
||||
*
|
||||
* @package twig
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class Twig_Error_Syntax extends Twig_Error
|
||||
{
|
28
lib/twig/ExistsLoaderInterface.php
Normal file
28
lib/twig/ExistsLoaderInterface.php
Normal file
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2009 Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Adds an exists() method for loaders.
|
||||
*
|
||||
* @author Florin Patan <florinpatan@gmail.com>
|
||||
* @deprecated since 1.12 (to be removed in 2.0)
|
||||
*/
|
||||
interface Twig_ExistsLoaderInterface
|
||||
{
|
||||
/**
|
||||
* Check if we have the source code of a template, given its name.
|
||||
*
|
||||
* @param string $name The name of the template to check if we can load
|
||||
*
|
||||
* @return boolean If the template source code is handled by this loader or not
|
||||
*/
|
||||
public function exists($name);
|
||||
}
|
184
lib/twig/lib/Twig/ExpressionParser.php → lib/twig/ExpressionParser.php
Executable file → Normal file
184
lib/twig/lib/Twig/ExpressionParser.php → lib/twig/ExpressionParser.php
Executable file → Normal file
|
@ -18,8 +18,7 @@
|
|||
* @see http://www.engr.mun.ca/~theo/Misc/exp_parsing.htm
|
||||
* @see http://en.wikipedia.org/wiki/Operator-precedence_parser
|
||||
*
|
||||
* @package twig
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class Twig_ExpressionParser
|
||||
{
|
||||
|
@ -89,9 +88,19 @@ class Twig_ExpressionParser
|
|||
{
|
||||
while ($this->parser->getStream()->test(Twig_Token::PUNCTUATION_TYPE, '?')) {
|
||||
$this->parser->getStream()->next();
|
||||
$expr2 = $this->parseExpression();
|
||||
$this->parser->getStream()->expect(Twig_Token::PUNCTUATION_TYPE, ':', 'The ternary operator must have a default value');
|
||||
$expr3 = $this->parseExpression();
|
||||
if (!$this->parser->getStream()->test(Twig_Token::PUNCTUATION_TYPE, ':')) {
|
||||
$expr2 = $this->parseExpression();
|
||||
if ($this->parser->getStream()->test(Twig_Token::PUNCTUATION_TYPE, ':')) {
|
||||
$this->parser->getStream()->next();
|
||||
$expr3 = $this->parseExpression();
|
||||
} else {
|
||||
$expr3 = new Twig_Node_Expression_Constant('', $this->parser->getCurrentToken()->getLine());
|
||||
}
|
||||
} else {
|
||||
$this->parser->getStream()->next();
|
||||
$expr2 = $expr;
|
||||
$expr3 = $this->parseExpression();
|
||||
}
|
||||
|
||||
$expr = new Twig_Node_Expression_Conditional($expr, $expr2, $expr3, $this->parser->getCurrentToken()->getLine());
|
||||
}
|
||||
|
@ -158,7 +167,7 @@ class Twig_ExpressionParser
|
|||
} elseif ($token->test(Twig_Token::PUNCTUATION_TYPE, '{')) {
|
||||
$node = $this->parseHashExpression();
|
||||
} else {
|
||||
throw new Twig_Error_Syntax(sprintf('Unexpected token "%s" of value "%s"', Twig_Token::typeToEnglish($token->getType(), $token->getLine()), $token->getValue()), $token->getLine());
|
||||
throw new Twig_Error_Syntax(sprintf('Unexpected token "%s" of value "%s"', Twig_Token::typeToEnglish($token->getType(), $token->getLine()), $token->getValue()), $token->getLine(), $this->parser->getFilename());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -252,7 +261,7 @@ class Twig_ExpressionParser
|
|||
} else {
|
||||
$current = $stream->getCurrent();
|
||||
|
||||
throw new Twig_Error_Syntax(sprintf('A hash key must be a quoted string, a number, a name, or an expression enclosed in parentheses (unexpected token "%s" of value "%s"', Twig_Token::typeToEnglish($current->getType(), $current->getLine()), $current->getValue()), $current->getLine());
|
||||
throw new Twig_Error_Syntax(sprintf('A hash key must be a quoted string, a number, a name, or an expression enclosed in parentheses (unexpected token "%s" of value "%s"', Twig_Token::typeToEnglish($current->getType(), $current->getLine()), $current->getValue()), $current->getLine(), $this->parser->getFilename());
|
||||
}
|
||||
|
||||
$stream->expect(Twig_Token::PUNCTUATION_TYPE, ':', 'A hash key must be followed by a colon (:)');
|
||||
|
@ -287,30 +296,31 @@ class Twig_ExpressionParser
|
|||
|
||||
public function getFunctionNode($name, $line)
|
||||
{
|
||||
$args = $this->parseArguments();
|
||||
switch ($name) {
|
||||
case 'parent':
|
||||
$args = $this->parseArguments();
|
||||
if (!count($this->parser->getBlockStack())) {
|
||||
throw new Twig_Error_Syntax('Calling "parent" outside a block is forbidden', $line);
|
||||
throw new Twig_Error_Syntax('Calling "parent" outside a block is forbidden', $line, $this->parser->getFilename());
|
||||
}
|
||||
|
||||
if (!$this->parser->getParent() && !$this->parser->hasTraits()) {
|
||||
throw new Twig_Error_Syntax('Calling "parent" on a template that does not extend nor "use" another template is forbidden', $line);
|
||||
throw new Twig_Error_Syntax('Calling "parent" on a template that does not extend nor "use" another template is forbidden', $line, $this->parser->getFilename());
|
||||
}
|
||||
|
||||
return new Twig_Node_Expression_Parent($this->parser->peekBlockStack(), $line);
|
||||
case 'block':
|
||||
return new Twig_Node_Expression_BlockReference($args->getNode(0), false, $line);
|
||||
return new Twig_Node_Expression_BlockReference($this->parseArguments()->getNode(0), false, $line);
|
||||
case 'attribute':
|
||||
$args = $this->parseArguments();
|
||||
if (count($args) < 2) {
|
||||
throw new Twig_Error_Syntax('The "attribute" function takes at least two arguments (the variable and the attributes)', $line);
|
||||
throw new Twig_Error_Syntax('The "attribute" function takes at least two arguments (the variable and the attributes)', $line, $this->parser->getFilename());
|
||||
}
|
||||
|
||||
return new Twig_Node_Expression_GetAttr($args->getNode(0), $args->getNode(1), count($args) > 2 ? $args->getNode(2) : new Twig_Node_Expression_Array(array(), $line), Twig_TemplateInterface::ANY_CALL, $line);
|
||||
default:
|
||||
if (null !== $alias = $this->parser->getImportedFunction($name)) {
|
||||
if (null !== $alias = $this->parser->getImportedSymbol('function', $name)) {
|
||||
$arguments = new Twig_Node_Expression_Array(array(), $line);
|
||||
foreach ($args as $n) {
|
||||
foreach ($this->parseArguments() as $n) {
|
||||
$arguments->addElement($n);
|
||||
}
|
||||
|
||||
|
@ -320,7 +330,8 @@ class Twig_ExpressionParser
|
|||
return $node;
|
||||
}
|
||||
|
||||
$class = $this->getFunctionNodeClass($name);
|
||||
$args = $this->parseArguments(true);
|
||||
$class = $this->getFunctionNodeClass($name, $line);
|
||||
|
||||
return new $class($name, $args, $line);
|
||||
}
|
||||
|
@ -351,24 +362,44 @@ class Twig_ExpressionParser
|
|||
}
|
||||
}
|
||||
} else {
|
||||
throw new Twig_Error_Syntax('Expected name or number', $lineno);
|
||||
throw new Twig_Error_Syntax('Expected name or number', $lineno, $this->parser->getFilename());
|
||||
}
|
||||
|
||||
if ($node instanceof Twig_Node_Expression_Name && null !== $alias = $this->parser->getImportedSymbol('template', $node->getAttribute('name'))) {
|
||||
if (!$arg instanceof Twig_Node_Expression_Constant) {
|
||||
throw new Twig_Error_Syntax(sprintf('Dynamic macro names are not supported (called on "%s")', $node->getAttribute('name')), $token->getLine(), $this->parser->getFilename());
|
||||
}
|
||||
|
||||
$node = new Twig_Node_Expression_MethodCall($node, 'get'.$arg->getAttribute('value'), $arguments, $lineno);
|
||||
$node->setAttribute('safe', true);
|
||||
|
||||
return $node;
|
||||
}
|
||||
} else {
|
||||
$type = Twig_TemplateInterface::ARRAY_CALL;
|
||||
|
||||
$arg = $this->parseExpression();
|
||||
|
||||
// slice?
|
||||
$slice = false;
|
||||
if ($stream->test(Twig_Token::PUNCTUATION_TYPE, ':')) {
|
||||
$stream->next();
|
||||
$slice = true;
|
||||
$arg = new Twig_Node_Expression_Constant(0, $token->getLine());
|
||||
} else {
|
||||
$arg = $this->parseExpression();
|
||||
}
|
||||
|
||||
if ($stream->test(Twig_Token::PUNCTUATION_TYPE, ':')) {
|
||||
$slice = true;
|
||||
$stream->next();
|
||||
}
|
||||
|
||||
if ($slice) {
|
||||
if ($stream->test(Twig_Token::PUNCTUATION_TYPE, ']')) {
|
||||
$length = new Twig_Node_Expression_Constant(null, $token->getLine());
|
||||
} else {
|
||||
$length = $this->parseExpression();
|
||||
}
|
||||
|
||||
$class = $this->getFilterNodeClass('slice');
|
||||
$class = $this->getFilterNodeClass('slice', $token->getLine());
|
||||
$arguments = new Twig_Node(array($arg, $length));
|
||||
$filter = new $class($node, new Twig_Node_Expression_Constant('slice', $token->getLine()), $arguments, $token->getLine());
|
||||
|
||||
|
@ -399,10 +430,10 @@ class Twig_ExpressionParser
|
|||
if (!$this->parser->getStream()->test(Twig_Token::PUNCTUATION_TYPE, '(')) {
|
||||
$arguments = new Twig_Node();
|
||||
} else {
|
||||
$arguments = $this->parseArguments();
|
||||
$arguments = $this->parseArguments(true);
|
||||
}
|
||||
|
||||
$class = $this->getFilterNodeClass($name->getAttribute('value'));
|
||||
$class = $this->getFilterNodeClass($name->getAttribute('value'), $token->getLine());
|
||||
|
||||
$node = new $class($node, $name, $arguments, $token->getLine(), $tag);
|
||||
|
||||
|
@ -416,17 +447,62 @@ class Twig_ExpressionParser
|
|||
return $node;
|
||||
}
|
||||
|
||||
public function parseArguments()
|
||||
/**
|
||||
* Parses arguments.
|
||||
*
|
||||
* @param Boolean $namedArguments Whether to allow named arguments or not
|
||||
* @param Boolean $definition Whether we are parsing arguments for a function definition
|
||||
*/
|
||||
public function parseArguments($namedArguments = false, $definition = false)
|
||||
{
|
||||
$args = array();
|
||||
$stream = $this->parser->getStream();
|
||||
|
||||
$stream->expect(Twig_Token::PUNCTUATION_TYPE, '(', 'A list of arguments must be opened by a parenthesis');
|
||||
$stream->expect(Twig_Token::PUNCTUATION_TYPE, '(', 'A list of arguments must begin with an opening parenthesis');
|
||||
while (!$stream->test(Twig_Token::PUNCTUATION_TYPE, ')')) {
|
||||
if (!empty($args)) {
|
||||
$stream->expect(Twig_Token::PUNCTUATION_TYPE, ',', 'Arguments must be separated by a comma');
|
||||
}
|
||||
$args[] = $this->parseExpression();
|
||||
|
||||
if ($definition) {
|
||||
$token = $stream->expect(Twig_Token::NAME_TYPE, null, 'An argument must be a name');
|
||||
$value = new Twig_Node_Expression_Name($token->getValue(), $this->parser->getCurrentToken()->getLine());
|
||||
} else {
|
||||
$value = $this->parseExpression();
|
||||
}
|
||||
|
||||
$name = null;
|
||||
if ($namedArguments && $stream->test(Twig_Token::OPERATOR_TYPE, '=')) {
|
||||
$token = $stream->next();
|
||||
if (!$value instanceof Twig_Node_Expression_Name) {
|
||||
throw new Twig_Error_Syntax(sprintf('A parameter name must be a string, "%s" given', get_class($value)), $token->getLine(), $this->parser->getFilename());
|
||||
}
|
||||
$name = $value->getAttribute('name');
|
||||
|
||||
if ($definition) {
|
||||
$value = $this->parsePrimaryExpression();
|
||||
|
||||
if (!$this->checkConstantExpression($value)) {
|
||||
throw new Twig_Error_Syntax(sprintf('A default value for an argument must be a constant (a boolean, a string, a number, or an array).'), $token->getLine(), $this->parser->getFilename());
|
||||
}
|
||||
} else {
|
||||
$value = $this->parseExpression();
|
||||
}
|
||||
}
|
||||
|
||||
if ($definition) {
|
||||
if (null === $name) {
|
||||
$name = $value->getAttribute('name');
|
||||
$value = new Twig_Node_Expression_Constant(null, $this->parser->getCurrentToken()->getLine());
|
||||
}
|
||||
$args[$name] = $value;
|
||||
} else {
|
||||
if (null === $name) {
|
||||
$args[] = $value;
|
||||
} else {
|
||||
$args[$name] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
$stream->expect(Twig_Token::PUNCTUATION_TYPE, ')', 'A list of arguments must be closed by a parenthesis');
|
||||
|
||||
|
@ -439,7 +515,7 @@ class Twig_ExpressionParser
|
|||
while (true) {
|
||||
$token = $this->parser->getStream()->expect(Twig_Token::NAME_TYPE, null, 'Only variables can be assigned to');
|
||||
if (in_array($token->getValue(), array('true', 'false', 'none'))) {
|
||||
throw new Twig_Error_Syntax(sprintf('You cannot assign a value to "%s"', $token->getValue()), $token->getLine());
|
||||
throw new Twig_Error_Syntax(sprintf('You cannot assign a value to "%s"', $token->getValue()), $token->getLine(), $this->parser->getFilename());
|
||||
}
|
||||
$targets[] = new Twig_Node_Expression_AssignName($token->getValue(), $token->getLine());
|
||||
|
||||
|
@ -466,23 +542,59 @@ class Twig_ExpressionParser
|
|||
return new Twig_Node($targets);
|
||||
}
|
||||
|
||||
protected function getFunctionNodeClass($name)
|
||||
protected function getFunctionNodeClass($name, $line)
|
||||
{
|
||||
$functionMap = $this->parser->getEnvironment()->getFunctions();
|
||||
if (isset($functionMap[$name]) && $functionMap[$name] instanceof Twig_Function_Node) {
|
||||
return $functionMap[$name]->getClass();
|
||||
$env = $this->parser->getEnvironment();
|
||||
|
||||
if (false === $function = $env->getFunction($name)) {
|
||||
$message = sprintf('The function "%s" does not exist', $name);
|
||||
if ($alternatives = $env->computeAlternatives($name, array_keys($env->getFunctions()))) {
|
||||
$message = sprintf('%s. Did you mean "%s"', $message, implode('", "', $alternatives));
|
||||
}
|
||||
|
||||
throw new Twig_Error_Syntax($message, $line, $this->parser->getFilename());
|
||||
}
|
||||
|
||||
return 'Twig_Node_Expression_Function';
|
||||
if ($function instanceof Twig_SimpleFunction) {
|
||||
return $function->getNodeClass();
|
||||
}
|
||||
|
||||
return $function instanceof Twig_Function_Node ? $function->getClass() : 'Twig_Node_Expression_Function';
|
||||
}
|
||||
|
||||
protected function getFilterNodeClass($name)
|
||||
protected function getFilterNodeClass($name, $line)
|
||||
{
|
||||
$filterMap = $this->parser->getEnvironment()->getFilters();
|
||||
if (isset($filterMap[$name]) && $filterMap[$name] instanceof Twig_Filter_Node) {
|
||||
return $filterMap[$name]->getClass();
|
||||
$env = $this->parser->getEnvironment();
|
||||
|
||||
if (false === $filter = $env->getFilter($name)) {
|
||||
$message = sprintf('The filter "%s" does not exist', $name);
|
||||
if ($alternatives = $env->computeAlternatives($name, array_keys($env->getFilters()))) {
|
||||
$message = sprintf('%s. Did you mean "%s"', $message, implode('", "', $alternatives));
|
||||
}
|
||||
|
||||
throw new Twig_Error_Syntax($message, $line, $this->parser->getFilename());
|
||||
}
|
||||
|
||||
return 'Twig_Node_Expression_Filter';
|
||||
if ($filter instanceof Twig_SimpleFilter) {
|
||||
return $filter->getNodeClass();
|
||||
}
|
||||
|
||||
return $filter instanceof Twig_Filter_Node ? $filter->getClass() : 'Twig_Node_Expression_Filter';
|
||||
}
|
||||
|
||||
// checks that the node only contains "constant" elements
|
||||
protected function checkConstantExpression(Twig_NodeInterface $node)
|
||||
{
|
||||
if (!($node instanceof Twig_Node_Expression_Constant || $node instanceof Twig_Node_Expression_Array)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ($node as $n) {
|
||||
if (!$this->checkConstantExpression($n)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
0
lib/twig/lib/Twig/Extension.php → lib/twig/Extension.php
Executable file → Normal file
0
lib/twig/lib/Twig/Extension.php → lib/twig/Extension.php
Executable file → Normal file
552
lib/twig/lib/Twig/Extension/Core.php → lib/twig/Extension/Core.php
Executable file → Normal file
552
lib/twig/lib/Twig/Extension/Core.php → lib/twig/Extension/Core.php
Executable file → Normal file
|
@ -48,7 +48,7 @@ class Twig_Extension_Core extends Twig_Extension
|
|||
/**
|
||||
* Sets the default timezone to be used by the date filter.
|
||||
*
|
||||
* @param DateTimeZone|string $timezone The default timezone string or a DateTimeZone object
|
||||
* @param DateTimeZone|string $timezone The default timezone string or a DateTimeZone object
|
||||
*/
|
||||
public function setTimezone($timezone)
|
||||
{
|
||||
|
@ -62,15 +62,19 @@ class Twig_Extension_Core extends Twig_Extension
|
|||
*/
|
||||
public function getTimezone()
|
||||
{
|
||||
if (null === $this->timezone) {
|
||||
$this->timezone = new DateTimeZone(date_default_timezone_get());
|
||||
}
|
||||
|
||||
return $this->timezone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the default format to be used by the number_format filter.
|
||||
*
|
||||
* @param integer $decimal The number of decimal places to use.
|
||||
* @param string $decimalPoint The character(s) to use for the decimal point.
|
||||
* @param string $thousandSep The character(s) to use for the thousands separator.
|
||||
* @param integer $decimal The number of decimal places to use.
|
||||
* @param string $decimalPoint The character(s) to use for the decimal point.
|
||||
* @param string $thousandSep The character(s) to use for the thousands separator.
|
||||
*/
|
||||
public function setNumberFormat($decimal, $decimalPoint, $thousandSep)
|
||||
{
|
||||
|
@ -109,6 +113,7 @@ class Twig_Extension_Core extends Twig_Extension
|
|||
new Twig_TokenParser_Spaceless(),
|
||||
new Twig_TokenParser_Flush(),
|
||||
new Twig_TokenParser_Do(),
|
||||
new Twig_TokenParser_Embed(),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -121,49 +126,53 @@ class Twig_Extension_Core extends Twig_Extension
|
|||
{
|
||||
$filters = array(
|
||||
// formatting filters
|
||||
'date' => new Twig_Filter_Function('twig_date_format_filter', array('needs_environment' => true)),
|
||||
'format' => new Twig_Filter_Function('sprintf'),
|
||||
'replace' => new Twig_Filter_Function('strtr'),
|
||||
'number_format' => new Twig_Filter_Function('twig_number_format_filter', array('needs_environment' => true)),
|
||||
new Twig_SimpleFilter('date', 'twig_date_format_filter', array('needs_environment' => true)),
|
||||
new Twig_SimpleFilter('date_modify', 'twig_date_modify_filter', array('needs_environment' => true)),
|
||||
new Twig_SimpleFilter('format', 'sprintf'),
|
||||
new Twig_SimpleFilter('replace', 'strtr'),
|
||||
new Twig_SimpleFilter('number_format', 'twig_number_format_filter', array('needs_environment' => true)),
|
||||
new Twig_SimpleFilter('abs', 'abs'),
|
||||
|
||||
// encoding
|
||||
'url_encode' => new Twig_Filter_Function('twig_urlencode_filter'),
|
||||
'json_encode' => new Twig_Filter_Function('twig_jsonencode_filter'),
|
||||
'convert_encoding' => new Twig_Filter_Function('twig_convert_encoding'),
|
||||
new Twig_SimpleFilter('url_encode', 'twig_urlencode_filter'),
|
||||
new Twig_SimpleFilter('json_encode', 'twig_jsonencode_filter'),
|
||||
new Twig_SimpleFilter('convert_encoding', 'twig_convert_encoding'),
|
||||
|
||||
// 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'),
|
||||
'trim' => new Twig_Filter_Function('trim'),
|
||||
'nl2br' => new Twig_Filter_Function('nl2br', array('pre_escape' => 'html', 'is_safe' => array('html'))),
|
||||
new Twig_SimpleFilter('title', 'twig_title_string_filter', array('needs_environment' => true)),
|
||||
new Twig_SimpleFilter('capitalize', 'twig_capitalize_string_filter', array('needs_environment' => true)),
|
||||
new Twig_SimpleFilter('upper', 'strtoupper'),
|
||||
new Twig_SimpleFilter('lower', 'strtolower'),
|
||||
new Twig_SimpleFilter('striptags', 'strip_tags'),
|
||||
new Twig_SimpleFilter('trim', 'trim'),
|
||||
new Twig_SimpleFilter('nl2br', 'nl2br', array('pre_escape' => 'html', 'is_safe' => array('html'))),
|
||||
|
||||
// array helpers
|
||||
'join' => new Twig_Filter_Function('twig_join_filter'),
|
||||
'sort' => new Twig_Filter_Function('twig_sort_filter'),
|
||||
'merge' => new Twig_Filter_Function('twig_array_merge'),
|
||||
new Twig_SimpleFilter('join', 'twig_join_filter'),
|
||||
new Twig_SimpleFilter('split', 'twig_split_filter'),
|
||||
new Twig_SimpleFilter('sort', 'twig_sort_filter'),
|
||||
new Twig_SimpleFilter('merge', 'twig_array_merge'),
|
||||
new Twig_SimpleFilter('batch', 'twig_array_batch'),
|
||||
|
||||
// string/array filters
|
||||
'reverse' => new Twig_Filter_Function('twig_reverse_filter', array('needs_environment' => true)),
|
||||
'length' => new Twig_Filter_Function('twig_length_filter', array('needs_environment' => true)),
|
||||
'slice' => new Twig_Filter_Function('twig_slice', array('needs_environment' => true)),
|
||||
new Twig_SimpleFilter('reverse', 'twig_reverse_filter', array('needs_environment' => true)),
|
||||
new Twig_SimpleFilter('length', 'twig_length_filter', array('needs_environment' => true)),
|
||||
new Twig_SimpleFilter('slice', 'twig_slice', array('needs_environment' => true)),
|
||||
new Twig_SimpleFilter('first', 'twig_first', array('needs_environment' => true)),
|
||||
new Twig_SimpleFilter('last', 'twig_last', array('needs_environment' => true)),
|
||||
|
||||
// iteration and runtime
|
||||
'default' => new Twig_Filter_Node('Twig_Node_Expression_Filter_Default'),
|
||||
'_default' => new Twig_Filter_Function('_twig_default_filter'),
|
||||
|
||||
'keys' => new Twig_Filter_Function('twig_get_array_keys_filter'),
|
||||
new Twig_SimpleFilter('default', '_twig_default_filter', array('node_class' => 'Twig_Node_Expression_Filter_Default')),
|
||||
new Twig_SimpleFilter('keys', 'twig_get_array_keys_filter'),
|
||||
|
||||
// escaping
|
||||
'escape' => new Twig_Filter_Function('twig_escape_filter', array('needs_environment' => true, 'is_safe_callback' => 'twig_escape_filter_is_safe')),
|
||||
'e' => new Twig_Filter_Function('twig_escape_filter', array('needs_environment' => true, 'is_safe_callback' => 'twig_escape_filter_is_safe')),
|
||||
new Twig_SimpleFilter('escape', 'twig_escape_filter', array('needs_environment' => true, 'is_safe_callback' => 'twig_escape_filter_is_safe')),
|
||||
new Twig_SimpleFilter('e', 'twig_escape_filter', array('needs_environment' => true, 'is_safe_callback' => 'twig_escape_filter_is_safe')),
|
||||
);
|
||||
|
||||
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));
|
||||
$filters[] = new Twig_SimpleFilter('upper', 'twig_upper_filter', array('needs_environment' => true));
|
||||
$filters[] = new Twig_SimpleFilter('lower', 'twig_lower_filter', array('needs_environment' => true));
|
||||
}
|
||||
|
||||
return $filters;
|
||||
|
@ -177,11 +186,12 @@ class Twig_Extension_Core extends Twig_Extension
|
|||
public function getFunctions()
|
||||
{
|
||||
return array(
|
||||
'range' => new Twig_Function_Function('range'),
|
||||
'constant' => new Twig_Function_Function('constant'),
|
||||
'cycle' => new Twig_Function_Function('twig_cycle'),
|
||||
'random' => new Twig_Function_Function('twig_random', array('needs_environment' => true)),
|
||||
'date' => new Twig_Function_Function('twig_date_converter', array('needs_environment' => true)),
|
||||
new Twig_SimpleFunction('range', 'range'),
|
||||
new Twig_SimpleFunction('constant', 'twig_constant'),
|
||||
new Twig_SimpleFunction('cycle', 'twig_cycle'),
|
||||
new Twig_SimpleFunction('random', 'twig_random', array('needs_environment' => true)),
|
||||
new Twig_SimpleFunction('date', 'twig_date_converter', array('needs_environment' => true)),
|
||||
new Twig_SimpleFunction('include', 'twig_include', array('needs_environment' => true, 'needs_context' => true)),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -193,15 +203,16 @@ class Twig_Extension_Core extends Twig_Extension
|
|||
public function getTests()
|
||||
{
|
||||
return array(
|
||||
'even' => new Twig_Test_Node('Twig_Node_Expression_Test_Even'),
|
||||
'odd' => new Twig_Test_Node('Twig_Node_Expression_Test_Odd'),
|
||||
'defined' => new Twig_Test_Node('Twig_Node_Expression_Test_Defined'),
|
||||
'sameas' => new Twig_Test_Node('Twig_Node_Expression_Test_Sameas'),
|
||||
'none' => new Twig_Test_Node('Twig_Node_Expression_Test_Null'),
|
||||
'null' => new Twig_Test_Node('Twig_Node_Expression_Test_Null'),
|
||||
'divisibleby' => new Twig_Test_Node('Twig_Node_Expression_Test_Divisibleby'),
|
||||
'constant' => new Twig_Test_Node('Twig_Node_Expression_Test_Constant'),
|
||||
'empty' => new Twig_Test_Function('twig_test_empty'),
|
||||
new Twig_SimpleTest('even', null, array('node_class' => 'Twig_Node_Expression_Test_Even')),
|
||||
new Twig_SimpleTest('odd', null, array('node_class' => 'Twig_Node_Expression_Test_Odd')),
|
||||
new Twig_SimpleTest('defined', null, array('node_class' => 'Twig_Node_Expression_Test_Defined')),
|
||||
new Twig_SimpleTest('sameas', null, array('node_class' => 'Twig_Node_Expression_Test_Sameas')),
|
||||
new Twig_SimpleTest('none', null, array('node_class' => 'Twig_Node_Expression_Test_Null')),
|
||||
new Twig_SimpleTest('null', null, array('node_class' => 'Twig_Node_Expression_Test_Null')),
|
||||
new Twig_SimpleTest('divisibleby', null, array('node_class' => 'Twig_Node_Expression_Test_Divisibleby')),
|
||||
new Twig_SimpleTest('constant', null, array('node_class' => 'Twig_Node_Expression_Test_Constant')),
|
||||
new Twig_SimpleTest('empty', 'twig_test_empty'),
|
||||
new Twig_SimpleTest('iterable', 'twig_test_iterable'),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -219,11 +230,11 @@ class Twig_Extension_Core extends Twig_Extension
|
|||
'+' => array('precedence' => 500, 'class' => 'Twig_Node_Expression_Unary_Pos'),
|
||||
),
|
||||
array(
|
||||
'b-and' => array('precedence' => 5, 'class' => 'Twig_Node_Expression_Binary_BitwiseAnd', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
||||
'b-xor' => array('precedence' => 5, 'class' => 'Twig_Node_Expression_Binary_BitwiseXor', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
||||
'b-or' => array('precedence' => 5, 'class' => 'Twig_Node_Expression_Binary_BitwiseOr', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
||||
'or' => array('precedence' => 10, 'class' => 'Twig_Node_Expression_Binary_Or', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
||||
'and' => array('precedence' => 15, 'class' => 'Twig_Node_Expression_Binary_And', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
||||
'b-or' => array('precedence' => 16, 'class' => 'Twig_Node_Expression_Binary_BitwiseOr', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
||||
'b-xor' => array('precedence' => 17, 'class' => 'Twig_Node_Expression_Binary_BitwiseXor', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
||||
'b-and' => array('precedence' => 18, 'class' => 'Twig_Node_Expression_Binary_BitwiseAnd', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
||||
'==' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_Equal', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
||||
'!=' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_NotEqual', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
||||
'<' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_Less', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
||||
|
@ -258,22 +269,32 @@ class Twig_Extension_Core extends Twig_Extension
|
|||
$name = $stream->expect(Twig_Token::NAME_TYPE)->getValue();
|
||||
$arguments = null;
|
||||
if ($stream->test(Twig_Token::PUNCTUATION_TYPE, '(')) {
|
||||
$arguments = $parser->getExpressionParser()->parseArguments();
|
||||
$arguments = $parser->getExpressionParser()->parseArguments(true);
|
||||
}
|
||||
|
||||
$class = $this->getTestNodeClass($parser->getEnvironment(), $name);
|
||||
$class = $this->getTestNodeClass($parser, $name, $node->getLine());
|
||||
|
||||
return new $class($node, $name, $arguments, $parser->getCurrentToken()->getLine());
|
||||
}
|
||||
|
||||
protected function getTestNodeClass(Twig_Environment $env, $name)
|
||||
protected function getTestNodeClass(Twig_Parser $parser, $name, $line)
|
||||
{
|
||||
$env = $parser->getEnvironment();
|
||||
$testMap = $env->getTests();
|
||||
if (isset($testMap[$name]) && $testMap[$name] instanceof Twig_Test_Node) {
|
||||
return $testMap[$name]->getClass();
|
||||
if (!isset($testMap[$name])) {
|
||||
$message = sprintf('The test "%s" does not exist', $name);
|
||||
if ($alternatives = $env->computeAlternatives($name, array_keys($env->getTests()))) {
|
||||
$message = sprintf('%s. Did you mean "%s"', $message, implode('", "', $alternatives));
|
||||
}
|
||||
|
||||
throw new Twig_Error_Syntax($message, $line, $parser->getFilename());
|
||||
}
|
||||
|
||||
return 'Twig_Node_Expression_Test';
|
||||
if ($testMap[$name] instanceof Twig_SimpleTest) {
|
||||
return $testMap[$name]->getNodeClass();
|
||||
}
|
||||
|
||||
return $testMap[$name] instanceof Twig_Test_Node ? $testMap[$name]->getClass() : 'Twig_Node_Expression_Test';
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -290,18 +311,18 @@ class Twig_Extension_Core extends Twig_Extension
|
|||
/**
|
||||
* Cycles over a value.
|
||||
*
|
||||
* @param ArrayAccess|array $values An array or an ArrayAccess instance
|
||||
* @param integer $i The cycle value
|
||||
* @param ArrayAccess|array $values An array or an ArrayAccess instance
|
||||
* @param integer $position The cycle position
|
||||
*
|
||||
* @return string The next value in the cycle
|
||||
*/
|
||||
function twig_cycle($values, $i)
|
||||
function twig_cycle($values, $position)
|
||||
{
|
||||
if (!is_array($values) && !$values instanceof ArrayAccess) {
|
||||
return $values;
|
||||
}
|
||||
|
||||
return $values[$i % count($values)];
|
||||
return $values[$position % count($values)];
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -310,8 +331,10 @@ function twig_cycle($values, $i)
|
|||
* - a random character from a string
|
||||
* - a random integer between 0 and the integer parameter
|
||||
*
|
||||
* @param Twig_Environment $env A Twig_Environment instance
|
||||
* @param Traversable|array|int|string $values The values to pick a random item from
|
||||
* @param Twig_Environment $env A Twig_Environment instance
|
||||
* @param Traversable|array|integer|string $values The values to pick a random item from
|
||||
*
|
||||
* @throws Twig_Error_Runtime When $values is an empty array (does not apply to an empty string which is returned as is).
|
||||
*
|
||||
* @return mixed A random value from the given sequence
|
||||
*/
|
||||
|
@ -328,6 +351,9 @@ function twig_random(Twig_Environment $env, $values = null)
|
|||
if ($values instanceof Traversable) {
|
||||
$values = iterator_to_array($values);
|
||||
} elseif (is_string($values)) {
|
||||
if ('' === $values) {
|
||||
return '';
|
||||
}
|
||||
if (null !== $charset = $env->getCharset()) {
|
||||
if ('UTF-8' != $charset) {
|
||||
$values = twig_convert_encoding($values, 'UTF-8', $charset);
|
||||
|
@ -370,7 +396,7 @@ function twig_random(Twig_Environment $env, $values = null)
|
|||
* @param string $format A format
|
||||
* @param DateTimeZone|string $timezone A timezone
|
||||
*
|
||||
* @return string The formatter date
|
||||
* @return string The formatted date
|
||||
*/
|
||||
function twig_date_format_filter(Twig_Environment $env, $date, $format = null, $timezone = null)
|
||||
{
|
||||
|
@ -379,17 +405,34 @@ function twig_date_format_filter(Twig_Environment $env, $date, $format = null, $
|
|||
$format = $date instanceof DateInterval ? $formats[1] : $formats[0];
|
||||
}
|
||||
|
||||
if ($date instanceof DateInterval || $date instanceof DateTime) {
|
||||
if (null !== $timezone) {
|
||||
$date->setTimezone($timezone instanceof DateTimeZone ? $timezone : new DateTimeZone($timezone));
|
||||
}
|
||||
|
||||
if ($date instanceof DateInterval) {
|
||||
return $date->format($format);
|
||||
}
|
||||
|
||||
return twig_date_converter($env, $date, $timezone)->format($format);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new date object modified
|
||||
*
|
||||
* <pre>
|
||||
* {{ post.published_at|date_modify("-1day")|date("m/d/Y") }}
|
||||
* </pre>
|
||||
*
|
||||
* @param Twig_Environment $env A Twig_Environment instance
|
||||
* @param DateTime|string $date A date
|
||||
* @param string $modifier A modifier string
|
||||
*
|
||||
* @return DateTime A new date object
|
||||
*/
|
||||
function twig_date_modify_filter(Twig_Environment $env, $date, $modifier)
|
||||
{
|
||||
$date = twig_date_converter($env, $date, false);
|
||||
$date->modify($modifier);
|
||||
|
||||
return $date;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts an input to a DateTime instance.
|
||||
*
|
||||
|
@ -407,28 +450,32 @@ function twig_date_format_filter(Twig_Environment $env, $date, $format = null, $
|
|||
*/
|
||||
function twig_date_converter(Twig_Environment $env, $date = null, $timezone = null)
|
||||
{
|
||||
// determine the timezone
|
||||
if (!$timezone) {
|
||||
$defaultTimezone = $env->getExtension('core')->getTimezone();
|
||||
} elseif (!$timezone instanceof DateTimeZone) {
|
||||
$defaultTimezone = new DateTimeZone($timezone);
|
||||
} else {
|
||||
$defaultTimezone = $timezone;
|
||||
}
|
||||
|
||||
if ($date instanceof DateTime) {
|
||||
$date = clone $date;
|
||||
if (false !== $timezone) {
|
||||
$date->setTimezone($defaultTimezone);
|
||||
}
|
||||
|
||||
return $date;
|
||||
}
|
||||
|
||||
$asString = (string) $date;
|
||||
|
||||
if (ctype_digit($asString) || (!empty($asString) && '-' === $asString[0] && ctype_digit(substr($asString, 1)))) {
|
||||
$date = new DateTime('@'.$date);
|
||||
$date->setTimezone(new DateTimeZone(date_default_timezone_get()));
|
||||
} else {
|
||||
$date = new DateTime($date);
|
||||
$date = '@'.$date;
|
||||
}
|
||||
|
||||
// set Timezone
|
||||
if (null !== $timezone) {
|
||||
if (!$timezone instanceof DateTimeZone) {
|
||||
$timezone = new DateTimeZone($timezone);
|
||||
}
|
||||
|
||||
$date->setTimezone($timezone);
|
||||
} elseif (($timezone = $env->getExtension('core')->getTimezone()) instanceof DateTimeZone) {
|
||||
$date->setTimezone($timezone);
|
||||
$date = new DateTime($date, $defaultTimezone);
|
||||
if (false !== $timezone) {
|
||||
$date->setTimezone($defaultTimezone);
|
||||
}
|
||||
|
||||
return $date;
|
||||
|
@ -443,7 +490,7 @@ function twig_date_converter(Twig_Environment $env, $date = null, $timezone = nu
|
|||
*
|
||||
* @param Twig_Environment $env A Twig_Environment instance
|
||||
* @param mixed $number A float/int/string of the number to format
|
||||
* @param int $decimal The number of decimal points to display.
|
||||
* @param integer $decimal The number of decimal points to display.
|
||||
* @param string $decimalPoint The character(s) to use for the decimal point.
|
||||
* @param string $thousandSep The character(s) to use for the thousands separator.
|
||||
*
|
||||
|
@ -468,15 +515,19 @@ function twig_number_format_filter(Twig_Environment $env, $number, $decimal = nu
|
|||
}
|
||||
|
||||
/**
|
||||
* URL encodes a string.
|
||||
* URL encodes a string as a path segment or an array as a query string.
|
||||
*
|
||||
* @param string $url A URL
|
||||
* @param bool $raw true to use rawurlencode() instead of urlencode
|
||||
* @param string|array $url A URL or an array of query parameters
|
||||
* @param bool $raw true to use rawurlencode() instead of urlencode
|
||||
*
|
||||
* @return string The URL encoded value
|
||||
*/
|
||||
function twig_urlencode_filter($url, $raw = false)
|
||||
{
|
||||
if (is_array($url)) {
|
||||
return http_build_query($url, '', '&');
|
||||
}
|
||||
|
||||
if ($raw) {
|
||||
return rawurlencode($url);
|
||||
}
|
||||
|
@ -586,6 +637,36 @@ function twig_slice(Twig_Environment $env, $item, $start, $length = null, $prese
|
|||
return null === $length ? substr($item, $start) : substr($item, $start, $length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the first element of the item.
|
||||
*
|
||||
* @param Twig_Environment $env A Twig_Environment instance
|
||||
* @param mixed $item A variable
|
||||
*
|
||||
* @return mixed The first element of the item
|
||||
*/
|
||||
function twig_first(Twig_Environment $env, $item)
|
||||
{
|
||||
$elements = twig_slice($env, $item, 0, 1, false);
|
||||
|
||||
return is_string($elements) ? $elements[0] : current($elements);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the last element of the item.
|
||||
*
|
||||
* @param Twig_Environment $env A Twig_Environment instance
|
||||
* @param mixed $item A variable
|
||||
*
|
||||
* @return mixed The last element of the item
|
||||
*/
|
||||
function twig_last(Twig_Environment $env, $item)
|
||||
{
|
||||
$elements = twig_slice($env, $item, -1, 1, false);
|
||||
|
||||
return is_string($elements) ? $elements[0] : current($elements);
|
||||
}
|
||||
|
||||
/**
|
||||
* Joins the values to a string.
|
||||
*
|
||||
|
@ -613,6 +694,38 @@ function twig_join_filter($value, $glue = '')
|
|||
return implode($glue, (array) $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Splits the string into an array.
|
||||
*
|
||||
* <pre>
|
||||
* {{ "one,two,three"|split(',') }}
|
||||
* {# returns [one, two, three] #}
|
||||
*
|
||||
* {{ "one,two,three,four,five"|split(',', 3) }}
|
||||
* {# returns [one, two, "three,four,five"] #}
|
||||
*
|
||||
* {{ "123"|split('') }}
|
||||
* {# returns [1, 2, 3] #}
|
||||
*
|
||||
* {{ "aabbcc"|split('', 2) }}
|
||||
* {# returns [aa, bb, cc] #}
|
||||
* </pre>
|
||||
*
|
||||
* @param string $value A string
|
||||
* @param string $delimiter The delimiter
|
||||
* @param integer $limit The limit
|
||||
*
|
||||
* @return array The split string as an array
|
||||
*/
|
||||
function twig_split_filter($value, $delimiter, $limit = null)
|
||||
{
|
||||
if (empty($delimiter)) {
|
||||
return str_split($value, null === $limit ? 1 : $limit);
|
||||
}
|
||||
|
||||
return null === $limit ? explode($delimiter, $value) : explode($delimiter, $value, $limit);
|
||||
}
|
||||
|
||||
// The '_default' filter is used internally to avoid using the ternary operator
|
||||
// which costs a lot for big contexts (before PHP 5.4). So, on average,
|
||||
// a function call is cheaper.
|
||||
|
@ -709,15 +822,15 @@ function twig_sort_filter($array)
|
|||
function twig_in_filter($value, $compare)
|
||||
{
|
||||
if (is_array($compare)) {
|
||||
return in_array($value, $compare);
|
||||
return in_array($value, $compare, is_object($value));
|
||||
} elseif (is_string($compare)) {
|
||||
if (!strlen((string) $value)) {
|
||||
if (!strlen($value)) {
|
||||
return empty($compare);
|
||||
}
|
||||
|
||||
return false !== strpos($compare, (string) $value);
|
||||
} elseif (is_object($compare) && $compare instanceof Traversable) {
|
||||
return in_array($value, iterator_to_array($compare, false));
|
||||
} elseif ($compare instanceof Traversable) {
|
||||
return in_array($value, iterator_to_array($compare, false), is_object($value));
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -728,11 +841,11 @@ function twig_in_filter($value, $compare)
|
|||
*
|
||||
* @param Twig_Environment $env A Twig_Environment instance
|
||||
* @param string $string The value to be escaped
|
||||
* @param string $type The escaping strategy
|
||||
* @param string $strategy The escaping strategy
|
||||
* @param string $charset The charset
|
||||
* @param Boolean $autoescape Whether the function is called by the auto-escaping feature (true) or by the developer (false)
|
||||
*/
|
||||
function twig_escape_filter(Twig_Environment $env, $string, $type = 'html', $charset = null, $autoescape = false)
|
||||
function twig_escape_filter(Twig_Environment $env, $string, $strategy = 'html', $charset = null, $autoescape = false)
|
||||
{
|
||||
if ($autoescape && is_object($string) && $string instanceof Twig_Markup) {
|
||||
return $string;
|
||||
|
@ -748,7 +861,7 @@ function twig_escape_filter(Twig_Environment $env, $string, $type = 'html', $cha
|
|||
|
||||
$string = (string) $string;
|
||||
|
||||
switch ($type) {
|
||||
switch ($strategy) {
|
||||
case 'js':
|
||||
// escape all non-alphanumeric characters
|
||||
// into their \xHH or \uHHHH representations
|
||||
|
@ -756,10 +869,46 @@ function twig_escape_filter(Twig_Environment $env, $string, $type = 'html', $cha
|
|||
$string = twig_convert_encoding($string, 'UTF-8', $charset);
|
||||
}
|
||||
|
||||
if (null === $string = preg_replace_callback('#[^\p{L}\p{N} ]#u', '_twig_escape_js_callback', $string)) {
|
||||
if (0 == strlen($string) ? false : (1 == preg_match('/^./su', $string) ? false : true)) {
|
||||
throw new Twig_Error_Runtime('The string to escape is not a valid UTF-8 string.');
|
||||
}
|
||||
|
||||
$string = preg_replace_callback('#[^a-zA-Z0-9,\._]#Su', '_twig_escape_js_callback', $string);
|
||||
|
||||
if ('UTF-8' != $charset) {
|
||||
$string = twig_convert_encoding($string, $charset, 'UTF-8');
|
||||
}
|
||||
|
||||
return $string;
|
||||
|
||||
case 'css':
|
||||
if ('UTF-8' != $charset) {
|
||||
$string = twig_convert_encoding($string, 'UTF-8', $charset);
|
||||
}
|
||||
|
||||
if (0 == strlen($string) ? false : (1 == preg_match('/^./su', $string) ? false : true)) {
|
||||
throw new Twig_Error_Runtime('The string to escape is not a valid UTF-8 string.');
|
||||
}
|
||||
|
||||
$string = preg_replace_callback('#[^a-zA-Z0-9]#Su', '_twig_escape_css_callback', $string);
|
||||
|
||||
if ('UTF-8' != $charset) {
|
||||
$string = twig_convert_encoding($string, $charset, 'UTF-8');
|
||||
}
|
||||
|
||||
return $string;
|
||||
|
||||
case 'html_attr':
|
||||
if ('UTF-8' != $charset) {
|
||||
$string = twig_convert_encoding($string, 'UTF-8', $charset);
|
||||
}
|
||||
|
||||
if (0 == strlen($string) ? false : (1 == preg_match('/^./su', $string) ? false : true)) {
|
||||
throw new Twig_Error_Runtime('The string to escape is not a valid UTF-8 string.');
|
||||
}
|
||||
|
||||
$string = preg_replace_callback('#[^a-zA-Z0-9,\.\-_]#Su', '_twig_escape_html_attr_callback', $string);
|
||||
|
||||
if ('UTF-8' != $charset) {
|
||||
$string = twig_convert_encoding($string, $charset, 'UTF-8');
|
||||
}
|
||||
|
@ -771,7 +920,7 @@ function twig_escape_filter(Twig_Environment $env, $string, $type = 'html', $cha
|
|||
|
||||
// Using a static variable to avoid initializing the array
|
||||
// each time the function is called. Moving the declaration on the
|
||||
// top of the function slow downs other escaping types.
|
||||
// top of the function slow downs other escaping strategies.
|
||||
static $htmlspecialcharsCharsets = array(
|
||||
'iso-8859-1' => true, 'iso8859-1' => true,
|
||||
'iso-8859-15' => true, 'iso8859-15' => true,
|
||||
|
@ -798,8 +947,15 @@ function twig_escape_filter(Twig_Environment $env, $string, $type = 'html', $cha
|
|||
|
||||
return twig_convert_encoding($string, $charset, 'UTF-8');
|
||||
|
||||
case 'url':
|
||||
if (version_compare(PHP_VERSION, '5.3.0', '<')) {
|
||||
return str_replace('%7E', '~', rawurlencode($string));
|
||||
}
|
||||
|
||||
return rawurlencode($string);
|
||||
|
||||
default:
|
||||
throw new Twig_Error_Runtime(sprintf('Invalid escape type "%s".', $type));
|
||||
throw new Twig_Error_Runtime(sprintf('Invalid escaping strategy "%s" (valid ones: html, js, url, css, and html_attr).', $strategy));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -817,16 +973,16 @@ function twig_escape_filter_is_safe(Twig_Node $filterArgs)
|
|||
return array('html');
|
||||
}
|
||||
|
||||
if (function_exists('iconv')) {
|
||||
function twig_convert_encoding($string, $to, $from)
|
||||
{
|
||||
return iconv($from, $to, $string);
|
||||
}
|
||||
} elseif (function_exists('mb_convert_encoding')) {
|
||||
if (function_exists('mb_convert_encoding')) {
|
||||
function twig_convert_encoding($string, $to, $from)
|
||||
{
|
||||
return mb_convert_encoding($string, $to, $from);
|
||||
}
|
||||
} elseif (function_exists('iconv')) {
|
||||
function twig_convert_encoding($string, $to, $from)
|
||||
{
|
||||
return iconv($from, $to, $string);
|
||||
}
|
||||
} else {
|
||||
function twig_convert_encoding($string, $to, $from)
|
||||
{
|
||||
|
@ -840,13 +996,89 @@ function _twig_escape_js_callback($matches)
|
|||
|
||||
// \xHH
|
||||
if (!isset($char[1])) {
|
||||
return '\\x'.substr('00'.bin2hex($char), -2);
|
||||
return '\\x'.strtoupper(substr('00'.bin2hex($char), -2));
|
||||
}
|
||||
|
||||
// \uHHHH
|
||||
$char = twig_convert_encoding($char, 'UTF-16BE', 'UTF-8');
|
||||
|
||||
return '\\u'.substr('0000'.bin2hex($char), -4);
|
||||
return '\\u'.strtoupper(substr('0000'.bin2hex($char), -4));
|
||||
}
|
||||
|
||||
function _twig_escape_css_callback($matches)
|
||||
{
|
||||
$char = $matches[0];
|
||||
|
||||
// \xHH
|
||||
if (!isset($char[1])) {
|
||||
$hex = ltrim(strtoupper(bin2hex($char)), '0');
|
||||
if (0 === strlen($hex)) {
|
||||
$hex = '0';
|
||||
}
|
||||
|
||||
return '\\'.$hex.' ';
|
||||
}
|
||||
|
||||
// \uHHHH
|
||||
$char = twig_convert_encoding($char, 'UTF-16BE', 'UTF-8');
|
||||
|
||||
return '\\'.ltrim(strtoupper(bin2hex($char)), '0').' ';
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is adapted from code coming from Zend Framework.
|
||||
*
|
||||
* @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
function _twig_escape_html_attr_callback($matches)
|
||||
{
|
||||
/*
|
||||
* While HTML supports far more named entities, the lowest common denominator
|
||||
* has become HTML5's XML Serialisation which is restricted to the those named
|
||||
* entities that XML supports. Using HTML entities would result in this error:
|
||||
* XML Parsing Error: undefined entity
|
||||
*/
|
||||
static $entityMap = array(
|
||||
34 => 'quot', /* quotation mark */
|
||||
38 => 'amp', /* ampersand */
|
||||
60 => 'lt', /* less-than sign */
|
||||
62 => 'gt', /* greater-than sign */
|
||||
);
|
||||
|
||||
$chr = $matches[0];
|
||||
$ord = ord($chr);
|
||||
|
||||
/**
|
||||
* The following replaces characters undefined in HTML with the
|
||||
* hex entity for the Unicode replacement character.
|
||||
*/
|
||||
if (($ord <= 0x1f && $chr != "\t" && $chr != "\n" && $chr != "\r") || ($ord >= 0x7f && $ord <= 0x9f)) {
|
||||
return '�';
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the current character to escape has a name entity we should
|
||||
* replace it with while grabbing the hex value of the character.
|
||||
*/
|
||||
if (strlen($chr) == 1) {
|
||||
$hex = strtoupper(substr('00'.bin2hex($chr), -2));
|
||||
} else {
|
||||
$chr = twig_convert_encoding($chr, 'UTF-16BE', 'UTF-8');
|
||||
$hex = strtoupper(substr('0000'.bin2hex($chr), -4));
|
||||
}
|
||||
|
||||
$int = hexdec($hex);
|
||||
if (array_key_exists($int, $entityMap)) {
|
||||
return sprintf('&%s;', $entityMap[$int]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Per OWASP recommendations, we'll use hex entities for any other
|
||||
* characters where a named entity does not exist.
|
||||
*/
|
||||
|
||||
return sprintf('&#x%s;', $hex);
|
||||
}
|
||||
|
||||
// add multibyte extensions if possible
|
||||
|
@ -934,8 +1166,7 @@ if (function_exists('mb_get_info')) {
|
|||
}
|
||||
}
|
||||
// and byte fallback
|
||||
else
|
||||
{
|
||||
else {
|
||||
/**
|
||||
* Returns the length of a variable.
|
||||
*
|
||||
|
@ -979,11 +1210,11 @@ else
|
|||
/* used internally */
|
||||
function twig_ensure_traversable($seq)
|
||||
{
|
||||
if (is_array($seq) || (is_object($seq) && $seq instanceof Traversable)) {
|
||||
if ($seq instanceof Traversable || is_array($seq)) {
|
||||
return $seq;
|
||||
} else {
|
||||
return array();
|
||||
}
|
||||
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1006,5 +1237,108 @@ function twig_test_empty($value)
|
|||
return 0 == count($value);
|
||||
}
|
||||
|
||||
return false === $value || (empty($value) && '0' != $value);
|
||||
return '' === $value || false === $value || null === $value || array() === $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a variable is traversable.
|
||||
*
|
||||
* <pre>
|
||||
* {# evaluates to true if the foo variable is an array or a traversable object #}
|
||||
* {% if foo is traversable %}
|
||||
* {# ... #}
|
||||
* {% endif %}
|
||||
* </pre>
|
||||
*
|
||||
* @param mixed $value A variable
|
||||
*
|
||||
* @return Boolean true if the value is traversable
|
||||
*/
|
||||
function twig_test_iterable($value)
|
||||
{
|
||||
return $value instanceof Traversable || is_array($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a template.
|
||||
*
|
||||
* @param string template The template to render
|
||||
* @param array variables The variables to pass to the template
|
||||
* @param Boolean with_context Whether to pass the current context variables or not
|
||||
* @param Boolean ignore_missing Whether to ignore missing templates or not
|
||||
* @param Boolean sandboxed Whether to sandbox the template or not
|
||||
*
|
||||
* @return string The rendered template
|
||||
*/
|
||||
function twig_include(Twig_Environment $env, $context, $template, $variables = array(), $withContext = true, $ignoreMissing = false, $sandboxed = false)
|
||||
{
|
||||
if ($withContext) {
|
||||
$variables = array_merge($context, $variables);
|
||||
}
|
||||
|
||||
if ($isSandboxed = $sandboxed && $env->hasExtension('sandbox')) {
|
||||
$sandbox = $env->getExtension('sandbox');
|
||||
if (!$alreadySandboxed = $sandbox->isSandboxed()) {
|
||||
$sandbox->enableSandbox();
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
return $env->resolveTemplate($template)->display($variables);
|
||||
} catch (Twig_Error_Loader $e) {
|
||||
if (!$ignoreMissing) {
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
if ($isSandboxed && !$alreadySandboxed) {
|
||||
$sandbox->disableSandbox();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the ability to get constants from instances as well as class/global constants.
|
||||
*
|
||||
* @param string $constant The name of the constant
|
||||
* @param null|object $object The object to get the constant from
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function twig_constant($constant, $object = null)
|
||||
{
|
||||
if (null !== $object) {
|
||||
$constant = get_class($object).'::'.$constant;
|
||||
}
|
||||
|
||||
return constant($constant);
|
||||
}
|
||||
|
||||
/**
|
||||
* Batches item.
|
||||
*
|
||||
* @param array $items An array of items
|
||||
* @param integer $size The size of the batch
|
||||
* @param string $fill A string to fill missing items
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function twig_array_batch($items, $size, $fill = null)
|
||||
{
|
||||
if ($items instanceof Traversable) {
|
||||
$items = iterator_to_array($items, false);
|
||||
}
|
||||
|
||||
$size = ceil($size);
|
||||
|
||||
$result = array_chunk($items, $size, true);
|
||||
|
||||
if (null !== $fill) {
|
||||
$last = count($result) - 1;
|
||||
$result[$last] = array_merge(
|
||||
$result[$last],
|
||||
array_fill(0, $size - count($result[$last]), $fill)
|
||||
);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
12
lib/twig/lib/Twig/Extension/Debug.php → lib/twig/Extension/Debug.php
Executable file → Normal file
12
lib/twig/lib/Twig/Extension/Debug.php → lib/twig/Extension/Debug.php
Executable file → Normal file
|
@ -17,11 +17,17 @@ class Twig_Extension_Debug extends Twig_Extension
|
|||
*/
|
||||
public function getFunctions()
|
||||
{
|
||||
// dump is safe if var_dump is overriden by xdebug
|
||||
$isDumpOutputHtmlSafe = extension_loaded('xdebug') && (false === get_cfg_var('xdebug.overload_var_dump') || get_cfg_var('xdebug.overload_var_dump')) && get_cfg_var('html_errors');
|
||||
// dump is safe if var_dump is overridden by xdebug
|
||||
$isDumpOutputHtmlSafe = extension_loaded('xdebug')
|
||||
// false means that it was not set (and the default is on) or it explicitly enabled
|
||||
&& (false === ini_get('xdebug.overload_var_dump') || ini_get('xdebug.overload_var_dump'))
|
||||
// false means that it was not set (and the default is on) or it explicitly enabled
|
||||
// xdebug.overload_var_dump produces HTML only when html_errors is also enabled
|
||||
&& (false === ini_get('html_errors') || ini_get('html_errors'))
|
||||
;
|
||||
|
||||
return array(
|
||||
'dump' => new Twig_Function_Function('twig_var_dump', array('is_safe' => $isDumpOutputHtmlSafe ? array('html') : array(), 'needs_context' => true, 'needs_environment' => true)),
|
||||
new Twig_SimpleFunction('dump', 'twig_var_dump', array('is_safe' => $isDumpOutputHtmlSafe ? array('html') : array(), 'needs_context' => true, 'needs_environment' => true)),
|
||||
);
|
||||
}
|
||||
|
44
lib/twig/lib/Twig/Extension/Escaper.php → lib/twig/Extension/Escaper.php
Executable file → Normal file
44
lib/twig/lib/Twig/Extension/Escaper.php → lib/twig/Extension/Escaper.php
Executable file → Normal file
|
@ -10,11 +10,11 @@
|
|||
*/
|
||||
class Twig_Extension_Escaper extends Twig_Extension
|
||||
{
|
||||
protected $autoescape;
|
||||
protected $defaultStrategy;
|
||||
|
||||
public function __construct($autoescape = true)
|
||||
public function __construct($defaultStrategy = 'html')
|
||||
{
|
||||
$this->autoescape = $autoescape;
|
||||
$this->setDefaultStrategy($defaultStrategy);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -45,13 +45,44 @@ class Twig_Extension_Escaper extends Twig_Extension
|
|||
public function getFilters()
|
||||
{
|
||||
return array(
|
||||
'raw' => new Twig_Filter_Function('twig_raw_filter', array('is_safe' => array('all'))),
|
||||
new Twig_SimpleFilter('raw', 'twig_raw_filter', array('is_safe' => array('all'))),
|
||||
);
|
||||
}
|
||||
|
||||
public function isGlobal()
|
||||
/**
|
||||
* Sets the default strategy to use when not defined by the user.
|
||||
*
|
||||
* The strategy can be a valid PHP callback that takes the template
|
||||
* "filename" as an argument and returns the strategy to use.
|
||||
*
|
||||
* @param mixed $defaultStrategy An escaping strategy
|
||||
*/
|
||||
public function setDefaultStrategy($defaultStrategy)
|
||||
{
|
||||
return $this->autoescape;
|
||||
// for BC
|
||||
if (true === $defaultStrategy) {
|
||||
$defaultStrategy = 'html';
|
||||
}
|
||||
|
||||
$this->defaultStrategy = $defaultStrategy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the default strategy to use when not defined by the user.
|
||||
*
|
||||
* @param string $filename The template "filename"
|
||||
*
|
||||
* @return string The default strategy to use for the template
|
||||
*/
|
||||
public function getDefaultStrategy($filename)
|
||||
{
|
||||
// disable string callables to avoid calling a function named html or js,
|
||||
// or any other upcoming escaping strategy
|
||||
if (!is_string($this->defaultStrategy) && is_callable($this->defaultStrategy)) {
|
||||
return call_user_func($this->defaultStrategy, $filename);
|
||||
}
|
||||
|
||||
return $this->defaultStrategy;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -74,4 +105,3 @@ function twig_raw_filter($string)
|
|||
{
|
||||
return $string;
|
||||
}
|
||||
|
0
lib/twig/lib/Twig/Extension/Optimizer.php → lib/twig/Extension/Optimizer.php
Executable file → Normal file
0
lib/twig/lib/Twig/Extension/Optimizer.php → lib/twig/Extension/Optimizer.php
Executable file → Normal file
0
lib/twig/lib/Twig/Extension/Sandbox.php → lib/twig/Extension/Sandbox.php
Executable file → Normal file
0
lib/twig/lib/Twig/Extension/Sandbox.php → lib/twig/Extension/Sandbox.php
Executable file → Normal file
113
lib/twig/Extension/Staging.php
Normal file
113
lib/twig/Extension/Staging.php
Normal file
|
@ -0,0 +1,113 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2012 Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Internal class.
|
||||
*
|
||||
* This class is used by Twig_Environment as a staging area and must not be used directly.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class Twig_Extension_Staging extends Twig_Extension
|
||||
{
|
||||
protected $functions = array();
|
||||
protected $filters = array();
|
||||
protected $visitors = array();
|
||||
protected $tokenParsers = array();
|
||||
protected $globals = array();
|
||||
protected $tests = array();
|
||||
|
||||
public function addFunction($name, $function)
|
||||
{
|
||||
$this->functions[$name] = $function;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFunctions()
|
||||
{
|
||||
return $this->functions;
|
||||
}
|
||||
|
||||
public function addFilter($name, $filter)
|
||||
{
|
||||
$this->filters[$name] = $filter;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFilters()
|
||||
{
|
||||
return $this->filters;
|
||||
}
|
||||
|
||||
public function addNodeVisitor(Twig_NodeVisitorInterface $visitor)
|
||||
{
|
||||
$this->visitors[] = $visitor;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getNodeVisitors()
|
||||
{
|
||||
return $this->visitors;
|
||||
}
|
||||
|
||||
public function addTokenParser(Twig_TokenParserInterface $parser)
|
||||
{
|
||||
$this->tokenParsers[] = $parser;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getTokenParsers()
|
||||
{
|
||||
return $this->tokenParsers;
|
||||
}
|
||||
|
||||
public function addGlobal($name, $value)
|
||||
{
|
||||
$this->globals[$name] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getGlobals()
|
||||
{
|
||||
return $this->globals;
|
||||
}
|
||||
|
||||
public function addTest($name, $test)
|
||||
{
|
||||
$this->tests[$name] = $test;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getTests()
|
||||
{
|
||||
return $this->tests;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'staging';
|
||||
}
|
||||
}
|
64
lib/twig/Extension/StringLoader.php
Normal file
64
lib/twig/Extension/StringLoader.php
Normal file
|
@ -0,0 +1,64 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2012 Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
class Twig_Extension_StringLoader extends Twig_Extension
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFunctions()
|
||||
{
|
||||
return array(
|
||||
new Twig_SimpleFunction('template_from_string', 'twig_template_from_string', array('needs_environment' => true)),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'string_loader';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a template from a string.
|
||||
*
|
||||
* <pre>
|
||||
* {% include template_from_string("Hello {{ name }}") }}
|
||||
* </pre>
|
||||
*
|
||||
* @param Twig_Environment $env A Twig_Environment instance
|
||||
* @param string $template A template as a string
|
||||
*
|
||||
* @return Twig_Template A Twig_Template instance
|
||||
*/
|
||||
function twig_template_from_string(Twig_Environment $env, $template)
|
||||
{
|
||||
static $loader;
|
||||
|
||||
if (null === $loader) {
|
||||
$loader = new Twig_Loader_String();
|
||||
}
|
||||
|
||||
$current = $env->getLoader();
|
||||
$env->setLoader($loader);
|
||||
try {
|
||||
$template = $env->loadTemplate($template);
|
||||
} catch (Exception $e) {
|
||||
$env->setLoader($current);
|
||||
|
||||
throw $e;
|
||||
}
|
||||
$env->setLoader($current);
|
||||
|
||||
return $template;
|
||||
}
|
21
lib/twig/lib/Twig/ExtensionInterface.php → lib/twig/ExtensionInterface.php
Executable file → Normal file
21
lib/twig/lib/Twig/ExtensionInterface.php → lib/twig/ExtensionInterface.php
Executable file → Normal file
|
@ -12,8 +12,7 @@
|
|||
/**
|
||||
* Interface implemented by extension classes.
|
||||
*
|
||||
* @package twig
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
interface Twig_ExtensionInterface
|
||||
{
|
||||
|
@ -24,61 +23,61 @@ interface Twig_ExtensionInterface
|
|||
*
|
||||
* @param Twig_Environment $environment The current Twig_Environment instance
|
||||
*/
|
||||
function initRuntime(Twig_Environment $environment);
|
||||
public function initRuntime(Twig_Environment $environment);
|
||||
|
||||
/**
|
||||
* Returns the token parser instances to add to the existing list.
|
||||
*
|
||||
* @return array An array of Twig_TokenParserInterface or Twig_TokenParserBrokerInterface instances
|
||||
*/
|
||||
function getTokenParsers();
|
||||
public function getTokenParsers();
|
||||
|
||||
/**
|
||||
* Returns the node visitor instances to add to the existing list.
|
||||
*
|
||||
* @return array An array of Twig_NodeVisitorInterface instances
|
||||
*/
|
||||
function getNodeVisitors();
|
||||
public function getNodeVisitors();
|
||||
|
||||
/**
|
||||
* Returns a list of filters to add to the existing list.
|
||||
*
|
||||
* @return array An array of filters
|
||||
*/
|
||||
function getFilters();
|
||||
public function getFilters();
|
||||
|
||||
/**
|
||||
* Returns a list of tests to add to the existing list.
|
||||
*
|
||||
* @return array An array of tests
|
||||
*/
|
||||
function getTests();
|
||||
public function getTests();
|
||||
|
||||
/**
|
||||
* Returns a list of functions to add to the existing list.
|
||||
*
|
||||
* @return array An array of functions
|
||||
*/
|
||||
function getFunctions();
|
||||
public function getFunctions();
|
||||
|
||||
/**
|
||||
* Returns a list of operators to add to the existing list.
|
||||
*
|
||||
* @return array An array of operators
|
||||
*/
|
||||
function getOperators();
|
||||
public function getOperators();
|
||||
|
||||
/**
|
||||
* Returns a list of global variables to add to the existing list.
|
||||
*
|
||||
* @return array An array of global variables
|
||||
*/
|
||||
function getGlobals();
|
||||
public function getGlobals();
|
||||
|
||||
/**
|
||||
* Returns the name of the extension.
|
||||
*
|
||||
* @return string The extension name
|
||||
*/
|
||||
function getName();
|
||||
public function getName();
|
||||
}
|
22
lib/twig/lib/Twig/Filter.php → lib/twig/Filter.php
Executable file → Normal file
22
lib/twig/lib/Twig/Filter.php → lib/twig/Filter.php
Executable file → Normal file
|
@ -12,10 +12,12 @@
|
|||
/**
|
||||
* Represents a template filter.
|
||||
*
|
||||
* @package twig
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* Use Twig_SimpleFilter instead.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @deprecated since 1.12 (to be removed in 2.0)
|
||||
*/
|
||||
abstract class Twig_Filter implements Twig_FilterInterface
|
||||
abstract class Twig_Filter implements Twig_FilterInterface, Twig_FilterCallableInterface
|
||||
{
|
||||
protected $options;
|
||||
protected $arguments = array();
|
||||
|
@ -26,6 +28,8 @@ abstract class Twig_Filter implements Twig_FilterInterface
|
|||
'needs_environment' => false,
|
||||
'needs_context' => false,
|
||||
'pre_escape' => null,
|
||||
'preserves_safety' => null,
|
||||
'callable' => null,
|
||||
), $options);
|
||||
}
|
||||
|
||||
|
@ -59,11 +63,21 @@ abstract class Twig_Filter implements Twig_FilterInterface
|
|||
return call_user_func($this->options['is_safe_callback'], $filterArgs);
|
||||
}
|
||||
|
||||
return array();
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getPreservesSafety()
|
||||
{
|
||||
return $this->options['preserves_safety'];
|
||||
}
|
||||
|
||||
public function getPreEscape()
|
||||
{
|
||||
return $this->options['pre_escape'];
|
||||
}
|
||||
|
||||
public function getCallable()
|
||||
{
|
||||
return $this->options['callable'];
|
||||
}
|
||||
}
|
8
lib/twig/lib/Twig/Filter/Function.php → lib/twig/Filter/Function.php
Executable file → Normal file
8
lib/twig/lib/Twig/Filter/Function.php → lib/twig/Filter/Function.php
Executable file → Normal file
|
@ -12,8 +12,10 @@
|
|||
/**
|
||||
* Represents a function template filter.
|
||||
*
|
||||
* @package twig
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* Use Twig_SimpleFilter instead.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @deprecated since 1.12 (to be removed in 2.0)
|
||||
*/
|
||||
class Twig_Filter_Function extends Twig_Filter
|
||||
{
|
||||
|
@ -21,6 +23,8 @@ class Twig_Filter_Function extends Twig_Filter
|
|||
|
||||
public function __construct($function, array $options = array())
|
||||
{
|
||||
$options['callable'] = $function;
|
||||
|
||||
parent::__construct($options);
|
||||
|
||||
$this->function = $function;
|
11
lib/twig/lib/Twig/Filter/Method.php → lib/twig/Filter/Method.php
Executable file → Normal file
11
lib/twig/lib/Twig/Filter/Method.php → lib/twig/Filter/Method.php
Executable file → Normal file
|
@ -12,15 +12,20 @@
|
|||
/**
|
||||
* Represents a method template filter.
|
||||
*
|
||||
* @package twig
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* Use Twig_SimpleFilter instead.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @deprecated since 1.12 (to be removed in 2.0)
|
||||
*/
|
||||
class Twig_Filter_Method extends Twig_Filter
|
||||
{
|
||||
protected $extension, $method;
|
||||
protected $extension;
|
||||
protected $method;
|
||||
|
||||
public function __construct(Twig_ExtensionInterface $extension, $method, array $options = array())
|
||||
{
|
||||
$options['callable'] = array($extension, $method);
|
||||
|
||||
parent::__construct($options);
|
||||
|
||||
$this->extension = $extension;
|
6
lib/twig/lib/Twig/Filter/Node.php → lib/twig/Filter/Node.php
Executable file → Normal file
6
lib/twig/lib/Twig/Filter/Node.php → lib/twig/Filter/Node.php
Executable file → Normal file
|
@ -12,8 +12,10 @@
|
|||
/**
|
||||
* Represents a template filter as a node.
|
||||
*
|
||||
* @package twig
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* Use Twig_SimpleFilter instead.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @deprecated since 1.12 (to be removed in 2.0)
|
||||
*/
|
||||
class Twig_Filter_Node extends Twig_Filter
|
||||
{
|
23
lib/twig/FilterCallableInterface.php
Normal file
23
lib/twig/FilterCallableInterface.php
Normal file
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2012 Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Represents a callable template filter.
|
||||
*
|
||||
* Use Twig_SimpleFilter instead.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @deprecated since 1.12 (to be removed in 2.0)
|
||||
*/
|
||||
interface Twig_FilterCallableInterface
|
||||
{
|
||||
public function getCallable();
|
||||
}
|
42
lib/twig/FilterInterface.php
Normal file
42
lib/twig/FilterInterface.php
Normal file
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2010 Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Represents a template filter.
|
||||
*
|
||||
* Use Twig_SimpleFilter instead.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @deprecated since 1.12 (to be removed in 2.0)
|
||||
*/
|
||||
interface Twig_FilterInterface
|
||||
{
|
||||
/**
|
||||
* Compiles a filter.
|
||||
*
|
||||
* @return string The PHP code for the filter
|
||||
*/
|
||||
public function compile();
|
||||
|
||||
public function needsEnvironment();
|
||||
|
||||
public function needsContext();
|
||||
|
||||
public function getSafe(Twig_Node $filterArgs);
|
||||
|
||||
public function getPreservesSafety();
|
||||
|
||||
public function getPreEscape();
|
||||
|
||||
public function setArguments($arguments);
|
||||
|
||||
public function getArguments();
|
||||
}
|
14
lib/twig/lib/Twig/Function.php → lib/twig/Function.php
Executable file → Normal file
14
lib/twig/lib/Twig/Function.php → lib/twig/Function.php
Executable file → Normal file
|
@ -12,10 +12,12 @@
|
|||
/**
|
||||
* Represents a template function.
|
||||
*
|
||||
* @package twig
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* Use Twig_SimpleFunction instead.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @deprecated since 1.12 (to be removed in 2.0)
|
||||
*/
|
||||
abstract class Twig_Function implements Twig_FunctionInterface
|
||||
abstract class Twig_Function implements Twig_FunctionInterface, Twig_FunctionCallableInterface
|
||||
{
|
||||
protected $options;
|
||||
protected $arguments = array();
|
||||
|
@ -25,6 +27,7 @@ abstract class Twig_Function implements Twig_FunctionInterface
|
|||
$this->options = array_merge(array(
|
||||
'needs_environment' => false,
|
||||
'needs_context' => false,
|
||||
'callable' => null,
|
||||
), $options);
|
||||
}
|
||||
|
||||
|
@ -60,4 +63,9 @@ abstract class Twig_Function implements Twig_FunctionInterface
|
|||
|
||||
return array();
|
||||
}
|
||||
|
||||
public function getCallable()
|
||||
{
|
||||
return $this->options['callable'];
|
||||
}
|
||||
}
|
8
lib/twig/lib/Twig/Function/Function.php → lib/twig/Function/Function.php
Executable file → Normal file
8
lib/twig/lib/Twig/Function/Function.php → lib/twig/Function/Function.php
Executable file → Normal file
|
@ -13,8 +13,10 @@
|
|||
/**
|
||||
* Represents a function template function.
|
||||
*
|
||||
* @package twig
|
||||
* @author Arnaud Le Blanc <arnaud.lb@gmail.com>
|
||||
* Use Twig_SimpleFunction instead.
|
||||
*
|
||||
* @author Arnaud Le Blanc <arnaud.lb@gmail.com>
|
||||
* @deprecated since 1.12 (to be removed in 2.0)
|
||||
*/
|
||||
class Twig_Function_Function extends Twig_Function
|
||||
{
|
||||
|
@ -22,6 +24,8 @@ class Twig_Function_Function extends Twig_Function
|
|||
|
||||
public function __construct($function, array $options = array())
|
||||
{
|
||||
$options['callable'] = $function;
|
||||
|
||||
parent::__construct($options);
|
||||
|
||||
$this->function = $function;
|
11
lib/twig/lib/Twig/Function/Method.php → lib/twig/Function/Method.php
Executable file → Normal file
11
lib/twig/lib/Twig/Function/Method.php → lib/twig/Function/Method.php
Executable file → Normal file
|
@ -13,15 +13,20 @@
|
|||
/**
|
||||
* Represents a method template function.
|
||||
*
|
||||
* @package twig
|
||||
* @author Arnaud Le Blanc <arnaud.lb@gmail.com>
|
||||
* Use Twig_SimpleFunction instead.
|
||||
*
|
||||
* @author Arnaud Le Blanc <arnaud.lb@gmail.com>
|
||||
* @deprecated since 1.12 (to be removed in 2.0)
|
||||
*/
|
||||
class Twig_Function_Method extends Twig_Function
|
||||
{
|
||||
protected $extension, $method;
|
||||
protected $extension;
|
||||
protected $method;
|
||||
|
||||
public function __construct(Twig_ExtensionInterface $extension, $method, array $options = array())
|
||||
{
|
||||
$options['callable'] = array($extension, $method);
|
||||
|
||||
parent::__construct($options);
|
||||
|
||||
$this->extension = $extension;
|
8
lib/twig/lib/Twig/Function/Node.php → lib/twig/Function/Node.php
Executable file → Normal file
8
lib/twig/lib/Twig/Function/Node.php → lib/twig/Function/Node.php
Executable file → Normal file
|
@ -12,10 +12,12 @@
|
|||
/**
|
||||
* Represents a template function as a node.
|
||||
*
|
||||
* @package twig
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* Use Twig_SimpleFunction instead.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @deprecated since 1.12 (to be removed in 2.0)
|
||||
*/
|
||||
class Twig_Function_Node extends Twig_Filter
|
||||
class Twig_Function_Node extends Twig_Function
|
||||
{
|
||||
protected $class;
|
||||
|
23
lib/twig/FunctionCallableInterface.php
Normal file
23
lib/twig/FunctionCallableInterface.php
Normal file
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2012 Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Represents a callable template function.
|
||||
*
|
||||
* Use Twig_SimpleFunction instead.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @deprecated since 1.12 (to be removed in 2.0)
|
||||
*/
|
||||
interface Twig_FunctionCallableInterface
|
||||
{
|
||||
public function getCallable();
|
||||
}
|
18
lib/twig/lib/Twig/FunctionInterface.php → lib/twig/FunctionInterface.php
Executable file → Normal file
18
lib/twig/lib/Twig/FunctionInterface.php → lib/twig/FunctionInterface.php
Executable file → Normal file
|
@ -13,8 +13,10 @@
|
|||
/**
|
||||
* Represents a template function.
|
||||
*
|
||||
* @package twig
|
||||
* @author Arnaud Le Blanc <arnaud.lb@gmail.com>
|
||||
* Use Twig_SimpleFunction instead.
|
||||
*
|
||||
* @author Arnaud Le Blanc <arnaud.lb@gmail.com>
|
||||
* @deprecated since 1.12 (to be removed in 2.0)
|
||||
*/
|
||||
interface Twig_FunctionInterface
|
||||
{
|
||||
|
@ -23,15 +25,15 @@ interface Twig_FunctionInterface
|
|||
*
|
||||
* @return string The PHP code for the function
|
||||
*/
|
||||
function compile();
|
||||
public function compile();
|
||||
|
||||
function needsEnvironment();
|
||||
public function needsEnvironment();
|
||||
|
||||
function needsContext();
|
||||
public function needsContext();
|
||||
|
||||
function getSafe(Twig_Node $filterArgs);
|
||||
public function getSafe(Twig_Node $filterArgs);
|
||||
|
||||
function setArguments($arguments);
|
||||
public function setArguments($arguments);
|
||||
|
||||
function getArguments();
|
||||
public function getArguments();
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
Copyright (c) 2009 by the Twig Team, see AUTHORS for more details.
|
||||
|
||||
Some rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer in the documentation and/or other materials provided
|
||||
with the distribution.
|
||||
|
||||
* The names of the contributors may not be used to endorse or
|
||||
promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
28
lib/twig/lib/Twig/Lexer.php → lib/twig/Lexer.php
Executable file → Normal file
28
lib/twig/lib/Twig/Lexer.php → lib/twig/Lexer.php
Executable file → Normal file
|
@ -13,8 +13,7 @@
|
|||
/**
|
||||
* Lexes a template string.
|
||||
*
|
||||
* @package twig
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class Twig_Lexer implements Twig_LexerInterface
|
||||
{
|
||||
|
@ -30,6 +29,9 @@ class Twig_Lexer implements Twig_LexerInterface
|
|||
protected $filename;
|
||||
protected $options;
|
||||
protected $regexes;
|
||||
protected $position;
|
||||
protected $positions;
|
||||
protected $currentVarBlockLine;
|
||||
|
||||
const STATE_DATA = 0;
|
||||
const STATE_BLOCK = 1;
|
||||
|
@ -59,10 +61,10 @@ class Twig_Lexer implements Twig_LexerInterface
|
|||
$this->regexes = array(
|
||||
'lex_var' => '/\s*'.preg_quote($this->options['whitespace_trim'].$this->options['tag_variable'][1], '/').'\s*|\s*'.preg_quote($this->options['tag_variable'][1], '/').'/A',
|
||||
'lex_block' => '/\s*(?:'.preg_quote($this->options['whitespace_trim'].$this->options['tag_block'][1], '/').'\s*|\s*'.preg_quote($this->options['tag_block'][1], '/').')\n?/A',
|
||||
'lex_raw_data' => '/('.preg_quote($this->options['tag_block'][0].$this->options['whitespace_trim'], '/').'|'.preg_quote($this->options['tag_block'][0], '/').')\s*endraw\s*(?:'.preg_quote($this->options['whitespace_trim'].$this->options['tag_block'][1], '/').'\s*|\s*'.preg_quote($this->options['tag_block'][1], '/').')/s',
|
||||
'lex_raw_data' => '/('.preg_quote($this->options['tag_block'][0].$this->options['whitespace_trim'], '/').'|'.preg_quote($this->options['tag_block'][0], '/').')\s*(?:end%s)\s*(?:'.preg_quote($this->options['whitespace_trim'].$this->options['tag_block'][1], '/').'\s*|\s*'.preg_quote($this->options['tag_block'][1], '/').')/s',
|
||||
'operator' => $this->getOperatorRegex(),
|
||||
'lex_comment' => '/(?:'.preg_quote($this->options['whitespace_trim'], '/').preg_quote($this->options['tag_comment'][1], '/').'\s*|'.preg_quote($this->options['tag_comment'][1], '/').')\n?/s',
|
||||
'lex_block_raw' => '/\s*raw\s*(?:'.preg_quote($this->options['whitespace_trim'].$this->options['tag_block'][1], '/').'\s*|\s*'.preg_quote($this->options['tag_block'][1], '/').')/As',
|
||||
'lex_block_raw' => '/\s*(raw|verbatim)\s*(?:'.preg_quote($this->options['whitespace_trim'].$this->options['tag_block'][1], '/').'\s*|\s*'.preg_quote($this->options['tag_block'][1], '/').')/As',
|
||||
'lex_block_line' => '/\s*line\s+(\d+)\s*'.preg_quote($this->options['tag_block'][1], '/').'/As',
|
||||
'lex_tokens_start' => '/('.preg_quote($this->options['tag_variable'][0], '/').'|'.preg_quote($this->options['tag_block'][0], '/').'|'.preg_quote($this->options['tag_comment'][0], '/').')('.preg_quote($this->options['whitespace_trim'], '/').')?/s',
|
||||
'interpolation_start' => '/'.preg_quote($this->options['interpolation'][0], '/').'\s*/A',
|
||||
|
@ -73,8 +75,8 @@ class Twig_Lexer implements Twig_LexerInterface
|
|||
/**
|
||||
* Tokenizes a source code.
|
||||
*
|
||||
* @param string $code The source code
|
||||
* @param string $filename A unique identifier for the 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
|
||||
*/
|
||||
|
@ -176,7 +178,7 @@ class Twig_Lexer implements Twig_LexerInterface
|
|||
// raw data?
|
||||
if (preg_match($this->regexes['lex_block_raw'], $this->code, $match, null, $this->cursor)) {
|
||||
$this->moveCursor($match[0]);
|
||||
$this->lexRawData();
|
||||
$this->lexRawData($match[1]);
|
||||
// {% line \d+ %}
|
||||
} elseif (preg_match($this->regexes['lex_block_line'], $this->code, $match, null, $this->cursor)) {
|
||||
$this->moveCursor($match[0]);
|
||||
|
@ -184,12 +186,14 @@ class Twig_Lexer implements Twig_LexerInterface
|
|||
} else {
|
||||
$this->pushToken(Twig_Token::BLOCK_START_TYPE);
|
||||
$this->pushState(self::STATE_BLOCK);
|
||||
$this->currentVarBlockLine = $this->lineno;
|
||||
}
|
||||
break;
|
||||
|
||||
case $this->options['tag_variable'][0]:
|
||||
$this->pushToken(Twig_Token::VAR_START_TYPE);
|
||||
$this->pushState(self::STATE_VAR);
|
||||
$this->currentVarBlockLine = $this->lineno;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -223,7 +227,7 @@ class Twig_Lexer implements Twig_LexerInterface
|
|||
$this->moveCursor($match[0]);
|
||||
|
||||
if ($this->cursor >= $this->end) {
|
||||
throw new Twig_Error_Syntax(sprintf('Unexpected end of file: Unclosed "%s"', $this->state === self::STATE_BLOCK ? 'block' : 'variable'));
|
||||
throw new Twig_Error_Syntax(sprintf('Unclosed "%s"', $this->state === self::STATE_BLOCK ? 'block' : 'variable'), $this->currentVarBlockLine, $this->filename);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -284,10 +288,10 @@ class Twig_Lexer implements Twig_LexerInterface
|
|||
}
|
||||
}
|
||||
|
||||
protected function lexRawData()
|
||||
protected function lexRawData($tag)
|
||||
{
|
||||
if (!preg_match($this->regexes['lex_raw_data'], $this->code, $match, PREG_OFFSET_CAPTURE, $this->cursor)) {
|
||||
throw new Twig_Error_Syntax(sprintf('Unexpected end of file: Unclosed "block"'));
|
||||
if (!preg_match(str_replace('%s', $tag, $this->regexes['lex_raw_data']), $this->code, $match, PREG_OFFSET_CAPTURE, $this->cursor)) {
|
||||
throw new Twig_Error_Syntax(sprintf('Unexpected end of file: Unclosed "%s" block', $tag), $this->lineno, $this->filename);
|
||||
}
|
||||
|
||||
$text = substr($this->code, $this->cursor, $match[0][1] - $this->cursor);
|
||||
|
@ -330,8 +334,6 @@ class Twig_Lexer implements Twig_LexerInterface
|
|||
|
||||
$this->popState();
|
||||
++$this->cursor;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
10
lib/twig/lib/Twig/LexerInterface.php → lib/twig/LexerInterface.php
Executable file → Normal file
10
lib/twig/lib/Twig/LexerInterface.php → lib/twig/LexerInterface.php
Executable file → Normal file
|
@ -12,18 +12,18 @@
|
|||
/**
|
||||
* Interface implemented by lexer classes.
|
||||
*
|
||||
* @package twig
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @deprecated since 1.12 (to be removed in 2.0)
|
||||
*/
|
||||
interface Twig_LexerInterface
|
||||
{
|
||||
/**
|
||||
* Tokenizes a source code.
|
||||
*
|
||||
* @param string $code The source code
|
||||
* @param string $filename A unique identifier for the source code
|
||||
* @param string $code The source code
|
||||
* @param string $filename A unique identifier for the source code
|
||||
*
|
||||
* @return Twig_TokenStream A token stream instance
|
||||
*/
|
||||
function tokenize($code, $filename = null);
|
||||
public function tokenize($code, $filename = null);
|
||||
}
|
30
lib/twig/lib/Twig/Loader/Array.php → lib/twig/Loader/Array.php
Executable file → Normal file
30
lib/twig/lib/Twig/Loader/Array.php → lib/twig/Loader/Array.php
Executable file → Normal file
|
@ -17,10 +17,9 @@
|
|||
* source code of the template). If you don't want to see your cache grows out of
|
||||
* control, you need to take care of clearing the old cache file by yourself.
|
||||
*
|
||||
* @package twig
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class Twig_Loader_Array implements Twig_LoaderInterface
|
||||
class Twig_Loader_Array implements Twig_LoaderInterface, Twig_ExistsLoaderInterface
|
||||
{
|
||||
protected $templates;
|
||||
|
||||
|
@ -51,11 +50,7 @@ class Twig_Loader_Array implements Twig_LoaderInterface
|
|||
}
|
||||
|
||||
/**
|
||||
* Gets the source code of a template, given its name.
|
||||
*
|
||||
* @param string $name The name of the template to load
|
||||
*
|
||||
* @return string The template source code
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getSource($name)
|
||||
{
|
||||
|
@ -68,11 +63,15 @@ class Twig_Loader_Array implements Twig_LoaderInterface
|
|||
}
|
||||
|
||||
/**
|
||||
* Gets the cache key to use for the cache for a given template name.
|
||||
*
|
||||
* @param string $name The name of the template to load
|
||||
*
|
||||
* @return string The cache key
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function exists($name)
|
||||
{
|
||||
return isset($this->templates[(string) $name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCacheKey($name)
|
||||
{
|
||||
|
@ -85,10 +84,7 @@ class Twig_Loader_Array implements Twig_LoaderInterface
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns true if the template is still fresh.
|
||||
*
|
||||
* @param string $name The template name
|
||||
* @param timestamp $time The last modification time of the cached template
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isFresh($name, $time)
|
||||
{
|
135
lib/twig/Loader/Chain.php
Normal file
135
lib/twig/Loader/Chain.php
Normal file
|
@ -0,0 +1,135 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2011 Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Loads templates from other loaders.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class Twig_Loader_Chain implements Twig_LoaderInterface, Twig_ExistsLoaderInterface
|
||||
{
|
||||
private $hasSourceCache = array();
|
||||
protected $loaders;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param Twig_LoaderInterface[] $loaders An array of loader instances
|
||||
*/
|
||||
public function __construct(array $loaders = array())
|
||||
{
|
||||
$this->loaders = array();
|
||||
foreach ($loaders as $loader) {
|
||||
$this->addLoader($loader);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a loader instance.
|
||||
*
|
||||
* @param Twig_LoaderInterface $loader A Loader instance
|
||||
*/
|
||||
public function addLoader(Twig_LoaderInterface $loader)
|
||||
{
|
||||
$this->loaders[] = $loader;
|
||||
$this->hasSourceCache = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getSource($name)
|
||||
{
|
||||
$exceptions = array();
|
||||
foreach ($this->loaders as $loader) {
|
||||
if ($loader instanceof Twig_ExistsLoaderInterface && !$loader->exists($name)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
return $loader->getSource($name);
|
||||
} catch (Twig_Error_Loader $e) {
|
||||
$exceptions[] = $e->getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
throw new Twig_Error_Loader(sprintf('Template "%s" is not defined (%s).', $name, implode(', ', $exceptions)));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function exists($name)
|
||||
{
|
||||
$name = (string) $name;
|
||||
|
||||
if (isset($this->hasSourceCache[$name])) {
|
||||
return $this->hasSourceCache[$name];
|
||||
}
|
||||
|
||||
foreach ($this->loaders as $loader) {
|
||||
if ($loader instanceof Twig_ExistsLoaderInterface && $loader->exists($name)) {
|
||||
return $this->hasSourceCache[$name] = true;
|
||||
}
|
||||
|
||||
try {
|
||||
$loader->getSource($name);
|
||||
|
||||
return $this->hasSourceCache[$name] = true;
|
||||
} catch (Twig_Error_Loader $e) {
|
||||
}
|
||||
}
|
||||
|
||||
return $this->hasSourceCache[$name] = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCacheKey($name)
|
||||
{
|
||||
$exceptions = array();
|
||||
foreach ($this->loaders as $loader) {
|
||||
if ($loader instanceof Twig_ExistsLoaderInterface && !$loader->exists($name)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
return $loader->getCacheKey($name);
|
||||
} catch (Twig_Error_Loader $e) {
|
||||
$exceptions[] = get_class($loader).': '.$e->getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
throw new Twig_Error_Loader(sprintf('Template "%s" is not defined (%s).', $name, implode(' ', $exceptions)));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isFresh($name, $time)
|
||||
{
|
||||
$exceptions = array();
|
||||
foreach ($this->loaders as $loader) {
|
||||
if ($loader instanceof Twig_ExistsLoaderInterface && !$loader->exists($name)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
return $loader->isFresh($name, $time);
|
||||
} catch (Twig_Error_Loader $e) {
|
||||
$exceptions[] = get_class($loader).': '.$e->getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
throw new Twig_Error_Loader(sprintf('Template "%s" is not defined (%s).', $name, implode(' ', $exceptions)));
|
||||
}
|
||||
}
|
220
lib/twig/Loader/Filesystem.php
Normal file
220
lib/twig/Loader/Filesystem.php
Normal file
|
@ -0,0 +1,220 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2009 Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Loads template from the filesystem.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderInterface
|
||||
{
|
||||
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.
|
||||
*
|
||||
* @param string $namespace A path namespace
|
||||
*
|
||||
* @return array The array of paths where to look for templates
|
||||
*/
|
||||
public function getPaths($namespace = '__main__')
|
||||
{
|
||||
return isset($this->paths[$namespace]) ? $this->paths[$namespace] : array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the path namespaces.
|
||||
*
|
||||
* The "__main__" namespace is always defined.
|
||||
*
|
||||
* @return array The array of defined namespaces
|
||||
*/
|
||||
public function getNamespaces()
|
||||
{
|
||||
return array_keys($this->paths);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the paths where templates are stored.
|
||||
*
|
||||
* @param string|array $paths A path or an array of paths where to look for templates
|
||||
* @param string $namespace A path namespace
|
||||
*/
|
||||
public function setPaths($paths, $namespace = '__main__')
|
||||
{
|
||||
if (!is_array($paths)) {
|
||||
$paths = array($paths);
|
||||
}
|
||||
|
||||
$this->paths[$namespace] = array();
|
||||
foreach ($paths as $path) {
|
||||
$this->addPath($path, $namespace);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a path where templates are stored.
|
||||
*
|
||||
* @param string $path A path where to look for templates
|
||||
* @param string $namespace A path name
|
||||
*
|
||||
* @throws Twig_Error_Loader
|
||||
*/
|
||||
public function addPath($path, $namespace = '__main__')
|
||||
{
|
||||
// invalidate the cache
|
||||
$this->cache = array();
|
||||
|
||||
if (!is_dir($path)) {
|
||||
throw new Twig_Error_Loader(sprintf('The "%s" directory does not exist.', $path));
|
||||
}
|
||||
|
||||
$this->paths[$namespace][] = rtrim($path, '/\\');
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepends a path where templates are stored.
|
||||
*
|
||||
* @param string $path A path where to look for templates
|
||||
* @param string $namespace A path name
|
||||
*
|
||||
* @throws Twig_Error_Loader
|
||||
*/
|
||||
public function prependPath($path, $namespace = '__main__')
|
||||
{
|
||||
// invalidate the cache
|
||||
$this->cache = array();
|
||||
|
||||
if (!is_dir($path)) {
|
||||
throw new Twig_Error_Loader(sprintf('The "%s" directory does not exist.', $path));
|
||||
}
|
||||
|
||||
$path = rtrim($path, '/\\');
|
||||
|
||||
if (!isset($this->paths[$namespace])) {
|
||||
$this->paths[$namespace][] = $path;
|
||||
} else {
|
||||
array_unshift($this->paths[$namespace], $path);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getSource($name)
|
||||
{
|
||||
return file_get_contents($this->findTemplate($name));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCacheKey($name)
|
||||
{
|
||||
return $this->findTemplate($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function exists($name)
|
||||
{
|
||||
$name = (string) $name;
|
||||
if (isset($this->cache[$name])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
$this->findTemplate($name);
|
||||
|
||||
return true;
|
||||
} catch (Twig_Error_Loader $exception) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isFresh($name, $time)
|
||||
{
|
||||
return filemtime($this->findTemplate($name)) <= $time;
|
||||
}
|
||||
|
||||
protected function findTemplate($name)
|
||||
{
|
||||
$name = (string) $name;
|
||||
|
||||
// normalize name
|
||||
$name = preg_replace('#/{2,}#', '/', strtr($name, '\\', '/'));
|
||||
|
||||
if (isset($this->cache[$name])) {
|
||||
return $this->cache[$name];
|
||||
}
|
||||
|
||||
$this->validateName($name);
|
||||
|
||||
$namespace = '__main__';
|
||||
if (isset($name[0]) && '@' == $name[0]) {
|
||||
if (false === $pos = strpos($name, '/')) {
|
||||
throw new Twig_Error_Loader(sprintf('Malformed namespaced template name "%s" (expecting "@namespace/template_name").', $name));
|
||||
}
|
||||
|
||||
$namespace = substr($name, 1, $pos - 1);
|
||||
|
||||
$name = substr($name, $pos + 1);
|
||||
}
|
||||
|
||||
if (!isset($this->paths[$namespace])) {
|
||||
throw new Twig_Error_Loader(sprintf('There are no registered paths for namespace "%s".', $namespace));
|
||||
}
|
||||
|
||||
foreach ($this->paths[$namespace] as $path) {
|
||||
if (is_file($path.'/'.$name)) {
|
||||
return $this->cache[$name] = $path.'/'.$name;
|
||||
}
|
||||
}
|
||||
|
||||
throw new Twig_Error_Loader(sprintf('Unable to find template "%s" (looked into: %s).', $name, implode(', ', $this->paths[$namespace])));
|
||||
}
|
||||
|
||||
protected function validateName($name)
|
||||
{
|
||||
if (false !== strpos($name, "\0")) {
|
||||
throw new Twig_Error_Loader('A template name cannot contain NUL bytes.');
|
||||
}
|
||||
|
||||
$parts = explode('/', $name);
|
||||
$level = 0;
|
||||
foreach ($parts as $part) {
|
||||
if ('..' === $part) {
|
||||
--$level;
|
||||
} elseif ('.' !== $part) {
|
||||
++$level;
|
||||
}
|
||||
|
||||
if ($level < 0) {
|
||||
throw new Twig_Error_Loader(sprintf('Looks like you try to load a template outside configured directories (%s).', $name));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
34
lib/twig/lib/Twig/Loader/String.php → lib/twig/Loader/String.php
Executable file → Normal file
34
lib/twig/lib/Twig/Loader/String.php → lib/twig/Loader/String.php
Executable file → Normal file
|
@ -12,22 +12,21 @@
|
|||
/**
|
||||
* Loads a template from a string.
|
||||
*
|
||||
* This loader should only be used for unit testing as it has many limitations
|
||||
* (for instance, the include or extends tag does not make any sense for a string
|
||||
* loader).
|
||||
*
|
||||
* When using this loader with a cache mechanism, you should know that a new cache
|
||||
* key is generated each time a template content "changes" (the cache key being the
|
||||
* source code of the template). If you don't want to see your cache grows out of
|
||||
* control, you need to take care of clearing the old cache file by yourself.
|
||||
*
|
||||
* @package twig
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class Twig_Loader_String implements Twig_LoaderInterface
|
||||
class Twig_Loader_String implements Twig_LoaderInterface, Twig_ExistsLoaderInterface
|
||||
{
|
||||
/**
|
||||
* Gets the source code of a template, given its name.
|
||||
*
|
||||
* @param string $name The name of the template to load
|
||||
*
|
||||
* @return string The template source code
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getSource($name)
|
||||
{
|
||||
|
@ -35,11 +34,15 @@ class Twig_Loader_String implements Twig_LoaderInterface
|
|||
}
|
||||
|
||||
/**
|
||||
* Gets the cache key to use for the cache for a given template name.
|
||||
*
|
||||
* @param string $name The name of the template to load
|
||||
*
|
||||
* @return string The cache key
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function exists($name)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCacheKey($name)
|
||||
{
|
||||
|
@ -47,10 +50,7 @@ class Twig_Loader_String implements Twig_LoaderInterface
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns true if the template is still fresh.
|
||||
*
|
||||
* @param string $name The template name
|
||||
* @param timestamp $time The last modification time of the cached template
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isFresh($name, $time)
|
||||
{
|
13
lib/twig/lib/Twig/LoaderInterface.php → lib/twig/LoaderInterface.php
Executable file → Normal file
13
lib/twig/lib/Twig/LoaderInterface.php → lib/twig/LoaderInterface.php
Executable file → Normal file
|
@ -12,32 +12,31 @@
|
|||
/**
|
||||
* Interface all loaders must implement.
|
||||
*
|
||||
* @package twig
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
interface Twig_LoaderInterface
|
||||
{
|
||||
/**
|
||||
* Gets the source code of a template, given its name.
|
||||
*
|
||||
* @param string $name The name of the template to load
|
||||
* @param string $name The name of the template to load
|
||||
*
|
||||
* @return string The template source code
|
||||
*
|
||||
* @throws Twig_Error_Loader When $name is not found
|
||||
*/
|
||||
function getSource($name);
|
||||
public function getSource($name);
|
||||
|
||||
/**
|
||||
* Gets the cache key to use for the cache for a given template name.
|
||||
*
|
||||
* @param string $name The name of the template to load
|
||||
* @param string $name The name of the template to load
|
||||
*
|
||||
* @return string The cache key
|
||||
*
|
||||
* @throws Twig_Error_Loader When $name is not found
|
||||
*/
|
||||
function getCacheKey($name);
|
||||
public function getCacheKey($name);
|
||||
|
||||
/**
|
||||
* Returns true if the template is still fresh.
|
||||
|
@ -49,5 +48,5 @@ interface Twig_LoaderInterface
|
|||
*
|
||||
* @throws Twig_Error_Loader When $name is not found
|
||||
*/
|
||||
function isFresh($name, $time);
|
||||
public function isFresh($name, $time);
|
||||
}
|
3
lib/twig/lib/Twig/Markup.php → lib/twig/Markup.php
Executable file → Normal file
3
lib/twig/lib/Twig/Markup.php → lib/twig/Markup.php
Executable file → Normal file
|
@ -12,8 +12,7 @@
|
|||
/**
|
||||
* Marks a content as safe.
|
||||
*
|
||||
* @package twig
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class Twig_Markup implements Countable
|
||||
{
|
9
lib/twig/lib/Twig/Node.php → lib/twig/Node.php
Executable file → Normal file
9
lib/twig/lib/Twig/Node.php → lib/twig/Node.php
Executable file → Normal file
|
@ -13,8 +13,7 @@
|
|||
/**
|
||||
* Represents a node in the AST.
|
||||
*
|
||||
* @package twig
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class Twig_Node implements Twig_NodeInterface
|
||||
{
|
||||
|
@ -134,12 +133,12 @@ class Twig_Node implements Twig_NodeInterface
|
|||
*
|
||||
* @param string The attribute name
|
||||
*
|
||||
* @return mixed The attribute value
|
||||
* @return mixed The attribute value
|
||||
*/
|
||||
public function getAttribute($name)
|
||||
{
|
||||
if (!array_key_exists($name, $this->attributes)) {
|
||||
throw new Twig_Error_Runtime(sprintf('Attribute "%s" does not exist for Node "%s".', $name, get_class($this)));
|
||||
throw new LogicException(sprintf('Attribute "%s" does not exist for Node "%s".', $name, get_class($this)));
|
||||
}
|
||||
|
||||
return $this->attributes[$name];
|
||||
|
@ -188,7 +187,7 @@ class Twig_Node implements Twig_NodeInterface
|
|||
public function getNode($name)
|
||||
{
|
||||
if (!array_key_exists($name, $this->nodes)) {
|
||||
throw new Twig_Error_Runtime(sprintf('Node "%s" does not exist for Node "%s".', $name, get_class($this)));
|
||||
throw new LogicException(sprintf('Node "%s" does not exist for Node "%s".', $name, get_class($this)));
|
||||
}
|
||||
|
||||
return $this->nodes[$name];
|
3
lib/twig/lib/Twig/Node/AutoEscape.php → lib/twig/Node/AutoEscape.php
Executable file → Normal file
3
lib/twig/lib/Twig/Node/AutoEscape.php → lib/twig/Node/AutoEscape.php
Executable file → Normal file
|
@ -18,8 +18,7 @@
|
|||
*
|
||||
* If autoescaping is disabled, then the value is false.
|
||||
*
|
||||
* @package twig
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class Twig_Node_AutoEscape extends Twig_Node
|
||||
{
|
3
lib/twig/lib/Twig/Node/Block.php → lib/twig/Node/Block.php
Executable file → Normal file
3
lib/twig/lib/Twig/Node/Block.php → lib/twig/Node/Block.php
Executable file → Normal file
|
@ -13,8 +13,7 @@
|
|||
/**
|
||||
* Represents a block node.
|
||||
*
|
||||
* @package twig
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class Twig_Node_Block extends Twig_Node
|
||||
{
|
3
lib/twig/lib/Twig/Node/BlockReference.php → lib/twig/Node/BlockReference.php
Executable file → Normal file
3
lib/twig/lib/Twig/Node/BlockReference.php → lib/twig/Node/BlockReference.php
Executable file → Normal file
|
@ -13,8 +13,7 @@
|
|||
/**
|
||||
* Represents a block call node.
|
||||
*
|
||||
* @package twig
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class Twig_Node_BlockReference extends Twig_Node implements Twig_NodeOutputInterface
|
||||
{
|
3
lib/twig/lib/Twig/Node/Body.php → lib/twig/Node/Body.php
Executable file → Normal file
3
lib/twig/lib/Twig/Node/Body.php → lib/twig/Node/Body.php
Executable file → Normal file
|
@ -12,8 +12,7 @@
|
|||
/**
|
||||
* Represents a body node.
|
||||
*
|
||||
* @package twig
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class Twig_Node_Body extends Twig_Node
|
||||
{
|
3
lib/twig/lib/Twig/Node/Do.php → lib/twig/Node/Do.php
Executable file → Normal file
3
lib/twig/lib/Twig/Node/Do.php → lib/twig/Node/Do.php
Executable file → Normal file
|
@ -12,8 +12,7 @@
|
|||
/**
|
||||
* Represents a do node.
|
||||
*
|
||||
* @package twig
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class Twig_Node_Do extends Twig_Node
|
||||
{
|
38
lib/twig/Node/Embed.php
Normal file
38
lib/twig/Node/Embed.php
Normal file
|
@ -0,0 +1,38 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2012 Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Represents an embed node.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class Twig_Node_Embed extends Twig_Node_Include
|
||||
{
|
||||
// we don't inject the module to avoid node visitors to traverse it twice (as it will be already visited in the main module)
|
||||
public function __construct($filename, $index, Twig_Node_Expression $variables = null, $only = false, $ignoreMissing = false, $lineno, $tag = null)
|
||||
{
|
||||
parent::__construct(new Twig_Node_Expression_Constant('not_used', $lineno), $variables, $only, $ignoreMissing, $lineno, $tag);
|
||||
|
||||
$this->setAttribute('filename', $filename);
|
||||
$this->setAttribute('index', $index);
|
||||
}
|
||||
|
||||
protected function addGetTemplate(Twig_Compiler $compiler)
|
||||
{
|
||||
$compiler
|
||||
->write("\$this->env->loadTemplate(")
|
||||
->string($this->getAttribute('filename'))
|
||||
->raw(', ')
|
||||
->string($this->getAttribute('index'))
|
||||
->raw(")")
|
||||
;
|
||||
}
|
||||
}
|
3
lib/twig/lib/Twig/Node/Expression.php → lib/twig/Node/Expression.php
Executable file → Normal file
3
lib/twig/lib/Twig/Node/Expression.php → lib/twig/Node/Expression.php
Executable file → Normal file
|
@ -13,8 +13,7 @@
|
|||
/**
|
||||
* Abstract class for all nodes that represents an expression.
|
||||
*
|
||||
* @package twig
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
abstract class Twig_Node_Expression extends Twig_Node
|
||||
{
|
0
lib/twig/lib/Twig/Node/Expression/Array.php → lib/twig/Node/Expression/Array.php
Executable file → Normal file
0
lib/twig/lib/Twig/Node/Expression/Array.php → lib/twig/Node/Expression/Array.php
Executable file → Normal file
0
lib/twig/lib/Twig/Node/Expression/AssignName.php → lib/twig/Node/Expression/AssignName.php
Executable file → Normal file
0
lib/twig/lib/Twig/Node/Expression/AssignName.php → lib/twig/Node/Expression/AssignName.php
Executable file → Normal file
0
lib/twig/lib/Twig/Node/Expression/Binary.php → lib/twig/Node/Expression/Binary.php
Executable file → Normal file
0
lib/twig/lib/Twig/Node/Expression/Binary.php → lib/twig/Node/Expression/Binary.php
Executable file → Normal file
0
lib/twig/lib/Twig/Node/Expression/Binary/Add.php → lib/twig/Node/Expression/Binary/Add.php
Executable file → Normal file
0
lib/twig/lib/Twig/Node/Expression/Binary/Add.php → lib/twig/Node/Expression/Binary/Add.php
Executable file → Normal file
0
lib/twig/lib/Twig/Node/Expression/Binary/And.php → lib/twig/Node/Expression/Binary/And.php
Executable file → Normal file
0
lib/twig/lib/Twig/Node/Expression/Binary/And.php → lib/twig/Node/Expression/Binary/And.php
Executable file → Normal file
0
lib/twig/lib/Twig/Node/Expression/Binary/BitwiseAnd.php → lib/twig/Node/Expression/Binary/BitwiseAnd.php
Executable file → Normal file
0
lib/twig/lib/Twig/Node/Expression/Binary/BitwiseAnd.php → lib/twig/Node/Expression/Binary/BitwiseAnd.php
Executable file → Normal file
0
lib/twig/lib/Twig/Node/Expression/Binary/BitwiseOr.php → lib/twig/Node/Expression/Binary/BitwiseOr.php
Executable file → Normal file
0
lib/twig/lib/Twig/Node/Expression/Binary/BitwiseOr.php → lib/twig/Node/Expression/Binary/BitwiseOr.php
Executable file → Normal file
0
lib/twig/lib/Twig/Node/Expression/Binary/BitwiseXor.php → lib/twig/Node/Expression/Binary/BitwiseXor.php
Executable file → Normal file
0
lib/twig/lib/Twig/Node/Expression/Binary/BitwiseXor.php → lib/twig/Node/Expression/Binary/BitwiseXor.php
Executable file → Normal file
0
lib/twig/lib/Twig/Node/Expression/Binary/Concat.php → lib/twig/Node/Expression/Binary/Concat.php
Executable file → Normal file
0
lib/twig/lib/Twig/Node/Expression/Binary/Concat.php → lib/twig/Node/Expression/Binary/Concat.php
Executable file → Normal file
0
lib/twig/lib/Twig/Node/Expression/Binary/Div.php → lib/twig/Node/Expression/Binary/Div.php
Executable file → Normal file
0
lib/twig/lib/Twig/Node/Expression/Binary/Div.php → lib/twig/Node/Expression/Binary/Div.php
Executable file → Normal file
0
lib/twig/lib/Twig/Node/Expression/Binary/Equal.php → lib/twig/Node/Expression/Binary/Equal.php
Executable file → Normal file
0
lib/twig/lib/Twig/Node/Expression/Binary/Equal.php → lib/twig/Node/Expression/Binary/Equal.php
Executable file → Normal file
0
lib/twig/lib/Twig/Node/Expression/Binary/FloorDiv.php → lib/twig/Node/Expression/Binary/FloorDiv.php
Executable file → Normal file
0
lib/twig/lib/Twig/Node/Expression/Binary/FloorDiv.php → lib/twig/Node/Expression/Binary/FloorDiv.php
Executable file → Normal file
0
lib/twig/lib/Twig/Node/Expression/Binary/Greater.php → lib/twig/Node/Expression/Binary/Greater.php
Executable file → Normal file
0
lib/twig/lib/Twig/Node/Expression/Binary/Greater.php → lib/twig/Node/Expression/Binary/Greater.php
Executable file → Normal file
0
lib/twig/lib/Twig/Node/Expression/Binary/GreaterEqual.php → lib/twig/Node/Expression/Binary/GreaterEqual.php
Executable file → Normal file
0
lib/twig/lib/Twig/Node/Expression/Binary/GreaterEqual.php → lib/twig/Node/Expression/Binary/GreaterEqual.php
Executable file → Normal file
0
lib/twig/lib/Twig/Node/Expression/Binary/In.php → lib/twig/Node/Expression/Binary/In.php
Executable file → Normal file
0
lib/twig/lib/Twig/Node/Expression/Binary/In.php → lib/twig/Node/Expression/Binary/In.php
Executable file → Normal file
0
lib/twig/lib/Twig/Node/Expression/Binary/Less.php → lib/twig/Node/Expression/Binary/Less.php
Executable file → Normal file
0
lib/twig/lib/Twig/Node/Expression/Binary/Less.php → lib/twig/Node/Expression/Binary/Less.php
Executable file → Normal file
0
lib/twig/lib/Twig/Node/Expression/Binary/LessEqual.php → lib/twig/Node/Expression/Binary/LessEqual.php
Executable file → Normal file
0
lib/twig/lib/Twig/Node/Expression/Binary/LessEqual.php → lib/twig/Node/Expression/Binary/LessEqual.php
Executable file → Normal file
0
lib/twig/lib/Twig/Node/Expression/Binary/Mod.php → lib/twig/Node/Expression/Binary/Mod.php
Executable file → Normal file
0
lib/twig/lib/Twig/Node/Expression/Binary/Mod.php → lib/twig/Node/Expression/Binary/Mod.php
Executable file → Normal file
0
lib/twig/lib/Twig/Node/Expression/Binary/Mul.php → lib/twig/Node/Expression/Binary/Mul.php
Executable file → Normal file
0
lib/twig/lib/Twig/Node/Expression/Binary/Mul.php → lib/twig/Node/Expression/Binary/Mul.php
Executable file → Normal file
0
lib/twig/lib/Twig/Node/Expression/Binary/NotEqual.php → lib/twig/Node/Expression/Binary/NotEqual.php
Executable file → Normal file
0
lib/twig/lib/Twig/Node/Expression/Binary/NotEqual.php → lib/twig/Node/Expression/Binary/NotEqual.php
Executable file → Normal file
0
lib/twig/lib/Twig/Node/Expression/Binary/NotIn.php → lib/twig/Node/Expression/Binary/NotIn.php
Executable file → Normal file
0
lib/twig/lib/Twig/Node/Expression/Binary/NotIn.php → lib/twig/Node/Expression/Binary/NotIn.php
Executable file → Normal file
0
lib/twig/lib/Twig/Node/Expression/Binary/Or.php → lib/twig/Node/Expression/Binary/Or.php
Executable file → Normal file
0
lib/twig/lib/Twig/Node/Expression/Binary/Or.php → lib/twig/Node/Expression/Binary/Or.php
Executable file → Normal file
0
lib/twig/lib/Twig/Node/Expression/Binary/Power.php → lib/twig/Node/Expression/Binary/Power.php
Executable file → Normal file
0
lib/twig/lib/Twig/Node/Expression/Binary/Power.php → lib/twig/Node/Expression/Binary/Power.php
Executable file → Normal file
0
lib/twig/lib/Twig/Node/Expression/Binary/Range.php → lib/twig/Node/Expression/Binary/Range.php
Executable file → Normal file
0
lib/twig/lib/Twig/Node/Expression/Binary/Range.php → lib/twig/Node/Expression/Binary/Range.php
Executable file → Normal file
0
lib/twig/lib/Twig/Node/Expression/Binary/Sub.php → lib/twig/Node/Expression/Binary/Sub.php
Executable file → Normal file
0
lib/twig/lib/Twig/Node/Expression/Binary/Sub.php → lib/twig/Node/Expression/Binary/Sub.php
Executable file → Normal file
3
lib/twig/lib/Twig/Node/Expression/BlockReference.php → lib/twig/Node/Expression/BlockReference.php
Executable file → Normal file
3
lib/twig/lib/Twig/Node/Expression/BlockReference.php → lib/twig/Node/Expression/BlockReference.php
Executable file → Normal file
|
@ -13,8 +13,7 @@
|
|||
/**
|
||||
* Represents a block call node.
|
||||
*
|
||||
* @package twig
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class Twig_Node_Expression_BlockReference extends Twig_Node_Expression
|
||||
{
|
171
lib/twig/Node/Expression/Call.php
Normal file
171
lib/twig/Node/Expression/Call.php
Normal file
|
@ -0,0 +1,171 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2012 Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
abstract class Twig_Node_Expression_Call extends Twig_Node_Expression
|
||||
{
|
||||
protected function compileCallable(Twig_Compiler $compiler)
|
||||
{
|
||||
$callable = $this->getAttribute('callable');
|
||||
|
||||
$closingParenthesis = false;
|
||||
if ($callable) {
|
||||
if (is_string($callable)) {
|
||||
$compiler->raw($callable);
|
||||
} elseif (is_array($callable) && $callable[0] instanceof Twig_ExtensionInterface) {
|
||||
$compiler->raw(sprintf('$this->env->getExtension(\'%s\')->%s', $callable[0]->getName(), $callable[1]));
|
||||
} else {
|
||||
$type = ucfirst($this->getAttribute('type'));
|
||||
$compiler->raw(sprintf('call_user_func_array($this->env->get%s(\'%s\')->getCallable(), array', $type, $this->getAttribute('name')));
|
||||
$closingParenthesis = true;
|
||||
}
|
||||
} else {
|
||||
$compiler->raw($this->getAttribute('thing')->compile());
|
||||
}
|
||||
|
||||
$this->compileArguments($compiler);
|
||||
|
||||
if ($closingParenthesis) {
|
||||
$compiler->raw(')');
|
||||
}
|
||||
}
|
||||
|
||||
protected function compileArguments(Twig_Compiler $compiler)
|
||||
{
|
||||
$compiler->raw('(');
|
||||
|
||||
$first = true;
|
||||
|
||||
if ($this->hasAttribute('needs_environment') && $this->getAttribute('needs_environment')) {
|
||||
$compiler->raw('$this->env');
|
||||
$first = false;
|
||||
}
|
||||
|
||||
if ($this->hasAttribute('needs_context') && $this->getAttribute('needs_context')) {
|
||||
if (!$first) {
|
||||
$compiler->raw(', ');
|
||||
}
|
||||
$compiler->raw('$context');
|
||||
$first = false;
|
||||
}
|
||||
|
||||
if ($this->hasAttribute('arguments')) {
|
||||
foreach ($this->getAttribute('arguments') as $argument) {
|
||||
if (!$first) {
|
||||
$compiler->raw(', ');
|
||||
}
|
||||
$compiler->string($argument);
|
||||
$first = false;
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->hasNode('node')) {
|
||||
if (!$first) {
|
||||
$compiler->raw(', ');
|
||||
}
|
||||
$compiler->subcompile($this->getNode('node'));
|
||||
$first = false;
|
||||
}
|
||||
|
||||
if ($this->hasNode('arguments') && null !== $this->getNode('arguments')) {
|
||||
$callable = $this->hasAttribute('callable') ? $this->getAttribute('callable') : null;
|
||||
|
||||
$arguments = $this->getArguments($callable, $this->getNode('arguments'));
|
||||
|
||||
foreach ($arguments as $node) {
|
||||
if (!$first) {
|
||||
$compiler->raw(', ');
|
||||
}
|
||||
$compiler->subcompile($node);
|
||||
$first = false;
|
||||
}
|
||||
}
|
||||
|
||||
$compiler->raw(')');
|
||||
}
|
||||
|
||||
protected function getArguments($callable, $arguments)
|
||||
{
|
||||
$parameters = array();
|
||||
$named = false;
|
||||
foreach ($arguments as $name => $node) {
|
||||
if (!is_int($name)) {
|
||||
$named = true;
|
||||
$name = $this->normalizeName($name);
|
||||
}
|
||||
$parameters[$name] = $node;
|
||||
}
|
||||
|
||||
if (!$named) {
|
||||
return $parameters;
|
||||
}
|
||||
|
||||
if (!$callable) {
|
||||
throw new LogicException(sprintf('Named arguments are not supported for %s "%s".', $this->getAttribute('type'), $this->getAttribute('name')));
|
||||
}
|
||||
|
||||
// manage named arguments
|
||||
if (is_array($callable)) {
|
||||
$r = new ReflectionMethod($callable[0], $callable[1]);
|
||||
} elseif (is_object($callable) && !$callable instanceof Closure) {
|
||||
$r = new ReflectionObject($callable);
|
||||
$r = $r->getMethod('__invoke');
|
||||
} else {
|
||||
$r = new ReflectionFunction($callable);
|
||||
}
|
||||
|
||||
$definition = $r->getParameters();
|
||||
if ($this->hasNode('node')) {
|
||||
array_shift($definition);
|
||||
}
|
||||
if ($this->hasAttribute('needs_environment') && $this->getAttribute('needs_environment')) {
|
||||
array_shift($definition);
|
||||
}
|
||||
if ($this->hasAttribute('needs_context') && $this->getAttribute('needs_context')) {
|
||||
array_shift($definition);
|
||||
}
|
||||
if ($this->hasAttribute('arguments') && null !== $this->getAttribute('arguments')) {
|
||||
foreach ($this->getAttribute('arguments') as $argument) {
|
||||
array_shift($definition);
|
||||
}
|
||||
}
|
||||
|
||||
$arguments = array();
|
||||
$pos = 0;
|
||||
foreach ($definition as $param) {
|
||||
$name = $this->normalizeName($param->name);
|
||||
|
||||
if (array_key_exists($name, $parameters)) {
|
||||
$arguments[] = $parameters[$name];
|
||||
unset($parameters[$name]);
|
||||
} elseif (array_key_exists($pos, $parameters)) {
|
||||
$arguments[] = $parameters[$pos];
|
||||
unset($parameters[$pos]);
|
||||
++$pos;
|
||||
} elseif ($param->isDefaultValueAvailable()) {
|
||||
$arguments[] = new Twig_Node_Expression_Constant($param->getDefaultValue(), -1);
|
||||
} elseif ($param->isOptional()) {
|
||||
break;
|
||||
} else {
|
||||
throw new Twig_Error_Syntax(sprintf('Value for argument "%s" is required for %s "%s".', $name, $this->getAttribute('type'), $this->getAttribute('name')));
|
||||
}
|
||||
}
|
||||
|
||||
foreach (array_keys($parameters) as $name) {
|
||||
throw new Twig_Error_Syntax(sprintf('Unknown argument "%s" for %s "%s".', $name, $this->getAttribute('type'), $this->getAttribute('name')));
|
||||
}
|
||||
|
||||
return $arguments;
|
||||
}
|
||||
|
||||
protected function normalizeName($name)
|
||||
{
|
||||
return strtolower(preg_replace(array('/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'), array('\\1_\\2', '\\1_\\2'), $name));
|
||||
}
|
||||
}
|
0
lib/twig/lib/Twig/Node/Expression/Conditional.php → lib/twig/Node/Expression/Conditional.php
Executable file → Normal file
0
lib/twig/lib/Twig/Node/Expression/Conditional.php → lib/twig/Node/Expression/Conditional.php
Executable file → Normal file
0
lib/twig/lib/Twig/Node/Expression/Constant.php → lib/twig/Node/Expression/Constant.php
Executable file → Normal file
0
lib/twig/lib/Twig/Node/Expression/Constant.php → lib/twig/Node/Expression/Constant.php
Executable file → Normal file
3
lib/twig/lib/Twig/Node/Expression/ExtensionReference.php → lib/twig/Node/Expression/ExtensionReference.php
Executable file → Normal file
3
lib/twig/lib/Twig/Node/Expression/ExtensionReference.php → lib/twig/Node/Expression/ExtensionReference.php
Executable file → Normal file
|
@ -12,8 +12,7 @@
|
|||
/**
|
||||
* Represents an extension call node.
|
||||
*
|
||||
* @package twig
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class Twig_Node_Expression_ExtensionReference extends Twig_Node_Expression
|
||||
{
|
36
lib/twig/Node/Expression/Filter.php
Normal file
36
lib/twig/Node/Expression/Filter.php
Normal file
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2009 Fabien Potencier
|
||||
* (c) 2009 Armin Ronacher
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
class Twig_Node_Expression_Filter extends Twig_Node_Expression_Call
|
||||
{
|
||||
public function __construct(Twig_NodeInterface $node, Twig_Node_Expression_Constant $filterName, Twig_NodeInterface $arguments, $lineno, $tag = null)
|
||||
{
|
||||
parent::__construct(array('node' => $node, 'filter' => $filterName, 'arguments' => $arguments), array(), $lineno, $tag);
|
||||
}
|
||||
|
||||
public function compile(Twig_Compiler $compiler)
|
||||
{
|
||||
$name = $this->getNode('filter')->getAttribute('value');
|
||||
$filter = $compiler->getEnvironment()->getFilter($name);
|
||||
|
||||
$this->setAttribute('name', $name);
|
||||
$this->setAttribute('type', 'filter');
|
||||
$this->setAttribute('thing', $filter);
|
||||
$this->setAttribute('needs_environment', $filter->needsEnvironment());
|
||||
$this->setAttribute('needs_context', $filter->needsContext());
|
||||
$this->setAttribute('arguments', $filter->getArguments());
|
||||
if ($filter instanceof Twig_FilterCallableInterface || $filter instanceof Twig_SimpleFilter) {
|
||||
$this->setAttribute('callable', $filter->getCallable());
|
||||
}
|
||||
|
||||
$this->compileCallable($compiler);
|
||||
}
|
||||
}
|
5
lib/twig/lib/Twig/Node/Expression/Filter/Default.php → lib/twig/Node/Expression/Filter/Default.php
Executable file → Normal file
5
lib/twig/lib/Twig/Node/Expression/Filter/Default.php → lib/twig/Node/Expression/Filter/Default.php
Executable file → Normal file
|
@ -16,14 +16,13 @@
|
|||
* {{ var.foo|default('foo item on var is not defined') }}
|
||||
* </pre>
|
||||
*
|
||||
* @package twig
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class Twig_Node_Expression_Filter_Default extends Twig_Node_Expression_Filter
|
||||
{
|
||||
public function __construct(Twig_NodeInterface $node, Twig_Node_Expression_Constant $filterName, Twig_NodeInterface $arguments, $lineno, $tag = null)
|
||||
{
|
||||
$default = new Twig_Node_Expression_Filter($node, new Twig_Node_Expression_Constant('_default', $node->getLine()), $arguments, $node->getLine());
|
||||
$default = new Twig_Node_Expression_Filter($node, new Twig_Node_Expression_Constant('default', $node->getLine()), $arguments, $node->getLine());
|
||||
|
||||
if ('default' === $filterName->getAttribute('value') && ($node instanceof Twig_Node_Expression_Name || $node instanceof Twig_Node_Expression_GetAttr)) {
|
||||
$test = new Twig_Node_Expression_Test_Defined(clone $node, 'defined', new Twig_Node(), $node->getLine());
|
35
lib/twig/Node/Expression/Function.php
Normal file
35
lib/twig/Node/Expression/Function.php
Normal file
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2010 Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
class Twig_Node_Expression_Function extends Twig_Node_Expression_Call
|
||||
{
|
||||
public function __construct($name, Twig_NodeInterface $arguments, $lineno)
|
||||
{
|
||||
parent::__construct(array('arguments' => $arguments), array('name' => $name), $lineno);
|
||||
}
|
||||
|
||||
public function compile(Twig_Compiler $compiler)
|
||||
{
|
||||
$name = $this->getAttribute('name');
|
||||
$function = $compiler->getEnvironment()->getFunction($name);
|
||||
|
||||
$this->setAttribute('name', $name);
|
||||
$this->setAttribute('type', 'function');
|
||||
$this->setAttribute('thing', $function);
|
||||
$this->setAttribute('needs_environment', $function->needsEnvironment());
|
||||
$this->setAttribute('needs_context', $function->needsContext());
|
||||
$this->setAttribute('arguments', $function->getArguments());
|
||||
if ($function instanceof Twig_FunctionCallableInterface || $function instanceof Twig_SimpleFunction) {
|
||||
$this->setAttribute('callable', $function->getCallable());
|
||||
}
|
||||
|
||||
$this->compileCallable($compiler);
|
||||
}
|
||||
}
|
4
lib/twig/lib/Twig/Node/Expression/GetAttr.php → lib/twig/Node/Expression/GetAttr.php
Executable file → Normal file
4
lib/twig/lib/Twig/Node/Expression/GetAttr.php → lib/twig/Node/Expression/GetAttr.php
Executable file → Normal file
|
@ -13,12 +13,12 @@ class Twig_Node_Expression_GetAttr extends Twig_Node_Expression
|
|||
{
|
||||
public function __construct(Twig_Node_Expression $node, Twig_Node_Expression $attribute, Twig_Node_Expression_Array $arguments, $type, $lineno)
|
||||
{
|
||||
parent::__construct(array('node' => $node, 'attribute' => $attribute, 'arguments' => $arguments), array('type' => $type, 'is_defined_test' => false, 'ignore_strict_check' => false), $lineno);
|
||||
parent::__construct(array('node' => $node, 'attribute' => $attribute, 'arguments' => $arguments), array('type' => $type, 'is_defined_test' => false, 'ignore_strict_check' => false, 'disable_c_ext' => false), $lineno);
|
||||
}
|
||||
|
||||
public function compile(Twig_Compiler $compiler)
|
||||
{
|
||||
if (function_exists('twig_template_get_attributes')) {
|
||||
if (function_exists('twig_template_get_attributes') && !$this->getAttribute('disable_c_ext')) {
|
||||
$compiler->raw('twig_template_get_attributes($this, ');
|
||||
} else {
|
||||
$compiler->raw('$this->getAttribute(');
|
4
lib/twig/lib/Twig/Node/Expression/MethodCall.php → lib/twig/Node/Expression/MethodCall.php
Executable file → Normal file
4
lib/twig/lib/Twig/Node/Expression/MethodCall.php → lib/twig/Node/Expression/MethodCall.php
Executable file → Normal file
|
@ -13,6 +13,10 @@ class Twig_Node_Expression_MethodCall extends Twig_Node_Expression
|
|||
public function __construct(Twig_Node_Expression $node, $method, Twig_Node_Expression_Array $arguments, $lineno)
|
||||
{
|
||||
parent::__construct(array('node' => $node, 'arguments' => $arguments), array('method' => $method, 'safe' => false), $lineno);
|
||||
|
||||
if ($node instanceof Twig_Node_Expression_Name) {
|
||||
$node->setAttribute('always_defined', true);
|
||||
}
|
||||
}
|
||||
|
||||
public function compile(Twig_Compiler $compiler)
|
18
lib/twig/lib/Twig/Node/Expression/Name.php → lib/twig/Node/Expression/Name.php
Executable file → Normal file
18
lib/twig/lib/Twig/Node/Expression/Name.php → lib/twig/Node/Expression/Name.php
Executable file → Normal file
|
@ -19,7 +19,7 @@ class Twig_Node_Expression_Name extends Twig_Node_Expression
|
|||
|
||||
public function __construct($name, $lineno)
|
||||
{
|
||||
parent::__construct(array(), array('name' => $name, 'is_defined_test' => false, 'ignore_strict_check' => false), $lineno);
|
||||
parent::__construct(array(), array('name' => $name, 'is_defined_test' => false, 'ignore_strict_check' => false, 'always_defined' => false), $lineno);
|
||||
}
|
||||
|
||||
public function compile(Twig_Compiler $compiler)
|
||||
|
@ -34,19 +34,31 @@ class Twig_Node_Expression_Name extends Twig_Node_Expression
|
|||
}
|
||||
} elseif ($this->isSpecial()) {
|
||||
$compiler->raw($this->specialVars[$name]);
|
||||
} elseif ($this->getAttribute('always_defined')) {
|
||||
$compiler
|
||||
->raw('$context[')
|
||||
->string($name)
|
||||
->raw(']')
|
||||
;
|
||||
} else {
|
||||
// remove the non-PHP 5.4 version when PHP 5.3 support is dropped
|
||||
// as the non-optimized version is just a workaround for slow ternary operator
|
||||
// when the context has a lot of variables
|
||||
if (version_compare(phpversion(), '5.4.0RC1', '>=') && ($this->getAttribute('ignore_strict_check') || !$compiler->getEnvironment()->isStrictVariables())) {
|
||||
if (version_compare(phpversion(), '5.4.0RC1', '>=')) {
|
||||
// PHP 5.4 ternary operator performance was optimized
|
||||
$compiler
|
||||
->raw('(isset($context[')
|
||||
->string($name)
|
||||
->raw(']) ? $context[')
|
||||
->string($name)
|
||||
->raw('] : null)')
|
||||
->raw('] : ')
|
||||
;
|
||||
|
||||
if ($this->getAttribute('ignore_strict_check') || !$compiler->getEnvironment()->isStrictVariables()) {
|
||||
$compiler->raw('null)');
|
||||
} else {
|
||||
$compiler->raw('$this->getContext($context, ')->string($name)->raw('))');
|
||||
}
|
||||
} else {
|
||||
$compiler
|
||||
->raw('$this->getContext($context, ')
|
3
lib/twig/lib/Twig/Node/Expression/Parent.php → lib/twig/Node/Expression/Parent.php
Executable file → Normal file
3
lib/twig/lib/Twig/Node/Expression/Parent.php → lib/twig/Node/Expression/Parent.php
Executable file → Normal file
|
@ -13,8 +13,7 @@
|
|||
/**
|
||||
* Represents a parent node.
|
||||
*
|
||||
* @package twig
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class Twig_Node_Expression_Parent extends Twig_Node_Expression
|
||||
{
|
6
lib/twig/lib/Twig/Node/Expression/TempName.php → lib/twig/Node/Expression/TempName.php
Executable file → Normal file
6
lib/twig/lib/Twig/Node/Expression/TempName.php → lib/twig/Node/Expression/TempName.php
Executable file → Normal file
|
@ -17,6 +17,10 @@ class Twig_Node_Expression_TempName extends Twig_Node_Expression
|
|||
|
||||
public function compile(Twig_Compiler $compiler)
|
||||
{
|
||||
$compiler->raw('$_')->raw($this->getAttribute('name'))->raw('_');
|
||||
$compiler
|
||||
->raw('$_')
|
||||
->raw($this->getAttribute('name'))
|
||||
->raw('_')
|
||||
;
|
||||
}
|
||||
}
|
32
lib/twig/Node/Expression/Test.php
Normal file
32
lib/twig/Node/Expression/Test.php
Normal file
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2010 Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
class Twig_Node_Expression_Test extends Twig_Node_Expression_Call
|
||||
{
|
||||
public function __construct(Twig_NodeInterface $node, $name, Twig_NodeInterface $arguments = null, $lineno)
|
||||
{
|
||||
parent::__construct(array('node' => $node, 'arguments' => $arguments), array('name' => $name), $lineno);
|
||||
}
|
||||
|
||||
public function compile(Twig_Compiler $compiler)
|
||||
{
|
||||
$name = $this->getAttribute('name');
|
||||
$test = $compiler->getEnvironment()->getTest($name);
|
||||
|
||||
$this->setAttribute('name', $name);
|
||||
$this->setAttribute('type', 'test');
|
||||
$this->setAttribute('thing', $test);
|
||||
if ($test instanceof Twig_TestCallableInterface || $test instanceof Twig_SimpleTest) {
|
||||
$this->setAttribute('callable', $test->getCallable());
|
||||
}
|
||||
|
||||
$this->compileCallable($compiler);
|
||||
}
|
||||
}
|
3
lib/twig/lib/Twig/Node/Expression/Test/Constant.php → lib/twig/Node/Expression/Test/Constant.php
Executable file → Normal file
3
lib/twig/lib/Twig/Node/Expression/Test/Constant.php → lib/twig/Node/Expression/Test/Constant.php
Executable file → Normal file
|
@ -18,8 +18,7 @@
|
|||
* {% endif %}
|
||||
* </pre>
|
||||
*
|
||||
* @package twig
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class Twig_Node_Expression_Test_Constant extends Twig_Node_Expression_Test
|
||||
{
|
5
lib/twig/lib/Twig/Node/Expression/Test/Defined.php → lib/twig/Node/Expression/Test/Defined.php
Executable file → Normal file
5
lib/twig/lib/Twig/Node/Expression/Test/Defined.php → lib/twig/Node/Expression/Test/Defined.php
Executable file → Normal file
|
@ -19,8 +19,7 @@
|
|||
* {% endif %}
|
||||
* </pre>
|
||||
*
|
||||
* @package twig
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class Twig_Node_Expression_Test_Defined extends Twig_Node_Expression_Test
|
||||
{
|
||||
|
@ -35,7 +34,7 @@ class Twig_Node_Expression_Test_Defined extends Twig_Node_Expression_Test
|
|||
|
||||
$this->changeIgnoreStrictCheck($node);
|
||||
} else {
|
||||
throw new Twig_Error_Syntax('The "defined" test only works with simple variables', $this->getLine());
|
||||
throw new Twig_Error_Syntax('The "defined" test only works with simple variables', $this->getLine(), $compiler->getFilename());
|
||||
}
|
||||
}
|
||||
|
3
lib/twig/lib/Twig/Node/Expression/Test/Divisibleby.php → lib/twig/Node/Expression/Test/Divisibleby.php
Executable file → Normal file
3
lib/twig/lib/Twig/Node/Expression/Test/Divisibleby.php → lib/twig/Node/Expression/Test/Divisibleby.php
Executable file → Normal file
|
@ -16,8 +16,7 @@
|
|||
* {% if loop.index is divisibleby(3) %}
|
||||
* </pre>
|
||||
*
|
||||
* @package twig
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class Twig_Node_Expression_Test_Divisibleby extends Twig_Node_Expression_Test
|
||||
{
|
3
lib/twig/lib/Twig/Node/Expression/Test/Even.php → lib/twig/Node/Expression/Test/Even.php
Executable file → Normal file
3
lib/twig/lib/Twig/Node/Expression/Test/Even.php → lib/twig/Node/Expression/Test/Even.php
Executable file → Normal file
|
@ -16,8 +16,7 @@
|
|||
* {{ var is even }}
|
||||
* </pre>
|
||||
*
|
||||
* @package twig
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class Twig_Node_Expression_Test_Even extends Twig_Node_Expression_Test
|
||||
{
|
3
lib/twig/lib/Twig/Node/Expression/Test/Null.php → lib/twig/Node/Expression/Test/Null.php
Executable file → Normal file
3
lib/twig/lib/Twig/Node/Expression/Test/Null.php → lib/twig/Node/Expression/Test/Null.php
Executable file → Normal file
|
@ -16,8 +16,7 @@
|
|||
* {{ var is none }}
|
||||
* </pre>
|
||||
*
|
||||
* @package twig
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class Twig_Node_Expression_Test_Null extends Twig_Node_Expression_Test
|
||||
{
|
3
lib/twig/lib/Twig/Node/Expression/Test/Odd.php → lib/twig/Node/Expression/Test/Odd.php
Executable file → Normal file
3
lib/twig/lib/Twig/Node/Expression/Test/Odd.php → lib/twig/Node/Expression/Test/Odd.php
Executable file → Normal file
|
@ -16,8 +16,7 @@
|
|||
* {{ var is odd }}
|
||||
* </pre>
|
||||
*
|
||||
* @package twig
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class Twig_Node_Expression_Test_Odd extends Twig_Node_Expression_Test
|
||||
{
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue