update Piwik to version 2.16 (fixes #91)
This commit is contained in:
parent
296343bf3b
commit
d885a4baa9
5833 changed files with 418860 additions and 226988 deletions
18
www/analytics/vendor/twig/twig/.editorconfig
vendored
18
www/analytics/vendor/twig/twig/.editorconfig
vendored
|
|
@ -1,18 +0,0 @@
|
|||
; top-most EditorConfig file
|
||||
root = true
|
||||
|
||||
; Unix-style newlines
|
||||
[*]
|
||||
end_of_line = LF
|
||||
|
||||
[*.php]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
[*.test]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
[*.rst]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
2
www/analytics/vendor/twig/twig/.gitignore
vendored
2
www/analytics/vendor/twig/twig/.gitignore
vendored
|
|
@ -1,2 +0,0 @@
|
|||
/ext/twig/autom4te.cache/
|
||||
|
||||
21
www/analytics/vendor/twig/twig/.travis.yml
vendored
21
www/analytics/vendor/twig/twig/.travis.yml
vendored
|
|
@ -1,21 +0,0 @@
|
|||
language: php
|
||||
|
||||
php:
|
||||
- 5.2
|
||||
- 5.3
|
||||
- 5.4
|
||||
- 5.5
|
||||
- hhvm
|
||||
|
||||
env:
|
||||
- TWIG_EXT=no
|
||||
- TWIG_EXT=yes
|
||||
|
||||
before_script:
|
||||
- if [ "$TWIG_EXT" == "yes" ]; then sh -c "cd ext/twig && phpize && ./configure --enable-twig && make && sudo make install"; fi
|
||||
- if [ "$TWIG_EXT" == "yes" ]; then echo "extension=twig.so" >> `php --ini | grep "Loaded Configuration" | sed -e "s|.*:\s*||"`; fi
|
||||
|
||||
matrix:
|
||||
exclude:
|
||||
- php: hhvm
|
||||
env: TWIG_EXT=yes
|
||||
124
www/analytics/vendor/twig/twig/CHANGELOG
vendored
124
www/analytics/vendor/twig/twig/CHANGELOG
vendored
|
|
@ -1,4 +1,126 @@
|
|||
* 1.15.1 (2013-02-13)
|
||||
* 1.22.3 (2015-10-13)
|
||||
|
||||
* fixed regression when using null as a cache strategy
|
||||
* improved performance when checking template freshness
|
||||
* fixed warnings when loaded templates do not exist
|
||||
* fixed template class name generation to prevent possible collisions
|
||||
* fixed logic for custom escapers to call them even on integers and null values
|
||||
* changed template cache names to take into account the Twig C extension
|
||||
|
||||
* 1.22.2 (2015-09-22)
|
||||
|
||||
* fixed a race condition in template loading
|
||||
|
||||
* 1.22.1 (2015-09-15)
|
||||
|
||||
* fixed regression in template_from_string
|
||||
|
||||
* 1.22.0 (2015-09-13)
|
||||
|
||||
* made Twig_Test_IntegrationTestCase more flexible
|
||||
* added an option to force PHP bytecode invalidation when writing a compiled template into the cache
|
||||
* fixed the profiler duration for the root node
|
||||
* changed template cache names to take into account enabled extensions
|
||||
* deprecated Twig_Environment::clearCacheFiles(), Twig_Environment::getCacheFilename(),
|
||||
Twig_Environment::writeCacheFile(), and Twig_Environment::getTemplateClassPrefix()
|
||||
* added a way to override the filesystem template cache system
|
||||
* added a way to get the original template source from Twig_Template
|
||||
|
||||
* 1.21.2 (2015-09-09)
|
||||
|
||||
* fixed variable names for the deprecation triggering code
|
||||
* fixed escaping strategy detection based on filename
|
||||
* added Traversable support for replace, merge, and sort
|
||||
* deprecated support for character by character replacement for the "replace" filter
|
||||
|
||||
* 1.21.1 (2015-08-26)
|
||||
|
||||
* fixed regression when using the deprecated Twig_Test_* classes
|
||||
|
||||
* 1.21.0 (2015-08-24)
|
||||
|
||||
* added deprecation notices for deprecated features
|
||||
* added a deprecation "framework" for filters/functions/tests and test fixtures
|
||||
|
||||
* 1.20.0 (2015-08-12)
|
||||
|
||||
* forbid access to the Twig environment from templates and internal parts of Twig_Template
|
||||
* fixed limited RCEs when in sandbox mode
|
||||
* deprecated Twig_Template::getEnvironment()
|
||||
* deprecated the _self variable for usage outside of the from and import tags
|
||||
* added Twig_BaseNodeVisitor to ease the compatibility of node visitors
|
||||
between 1.x and 2.x
|
||||
|
||||
* 1.19.0 (2015-07-31)
|
||||
|
||||
* fixed wrong error message when including an undefined template in a child template
|
||||
* added support for variadic filters, functions, and tests
|
||||
* added support for extra positional arguments in macros
|
||||
* added ignore_missing flag to the source function
|
||||
* fixed batch filter with zero items
|
||||
* deprecated Twig_Environment::clearTemplateCache()
|
||||
* fixed sandbox disabling when using the include function
|
||||
|
||||
* 1.18.2 (2015-06-06)
|
||||
|
||||
* fixed template/line guessing in exceptions for nested templates
|
||||
* optimized the number of inodes and the size of realpath cache when using the cache
|
||||
|
||||
* 1.18.1 (2015-04-19)
|
||||
|
||||
* fixed memory leaks in the C extension
|
||||
* deprecated Twig_Loader_String
|
||||
* fixed the slice filter when used with a SimpleXMLElement object
|
||||
* fixed filesystem loader when trying to load non-files (like directories)
|
||||
|
||||
* 1.18.0 (2015-01-25)
|
||||
|
||||
* fixed some error messages where the line was wrong (unknown variables or argument names)
|
||||
* added a new way to customize the main Module node (via empty nodes)
|
||||
* added Twig_Environment::createTemplate() to create a template from a string
|
||||
* added a profiler
|
||||
* fixed filesystem loader cache when different file paths are used for the same template
|
||||
|
||||
* 1.17.0 (2015-01-14)
|
||||
|
||||
* added a 'filename' autoescaping strategy, which dynamically chooses the
|
||||
autoescaping strategy for a template based on template file extension.
|
||||
|
||||
* 1.16.3 (2014-12-25)
|
||||
|
||||
* fixed regression for dynamic parent templates
|
||||
* fixed cache management with statcache
|
||||
* fixed a regression in the slice filter
|
||||
|
||||
* 1.16.2 (2014-10-17)
|
||||
|
||||
* fixed timezone on dates as strings
|
||||
* fixed 2-words test names when a custom node class is not used
|
||||
* fixed macros when using an argument named like a PHP super global (like GET or POST)
|
||||
* fixed date_modify when working with DateTimeImmutable
|
||||
* optimized for loops
|
||||
* fixed multi-byte characters handling in the split filter
|
||||
* fixed a regression in the in operator
|
||||
* fixed a regression in the slice filter
|
||||
|
||||
* 1.16.1 (2014-10-10)
|
||||
|
||||
* improved error reporting in a sandboxed template
|
||||
* fixed missing error file/line information under certain circumstances
|
||||
* fixed wrong error line number in some error messages
|
||||
* fixed the in operator to use strict comparisons
|
||||
* sped up the slice filter
|
||||
* fixed for mb function overload mb_substr acting different
|
||||
* fixed the attribute() function when passing a variable for the arguments
|
||||
|
||||
* 1.16.0 (2014-07-05)
|
||||
|
||||
* changed url_encode to always encode according to RFC 3986
|
||||
* fixed inheritance in a 'use'-hierarchy
|
||||
* removed the __toString policy check when the sandbox is disabled
|
||||
* fixed recursively calling blocks in templates with inheritance
|
||||
|
||||
* 1.15.1 (2014-02-13)
|
||||
|
||||
* fixed the conversion of the special '0000-00-00 00:00' date
|
||||
* added an error message when trying to import an undefined block from a trait
|
||||
|
|
|
|||
10
www/analytics/vendor/twig/twig/composer.json
vendored
10
www/analytics/vendor/twig/twig/composer.json
vendored
|
|
@ -14,7 +14,7 @@
|
|||
},
|
||||
{
|
||||
"name": "Twig Team",
|
||||
"homepage": "https://github.com/fabpot/Twig/graphs/contributors",
|
||||
"homepage": "http://twig.sensiolabs.org/contributors",
|
||||
"role": "Contributors"
|
||||
},
|
||||
{
|
||||
|
|
@ -27,7 +27,11 @@
|
|||
"forum": "https://groups.google.com/forum/#!forum/twig-users"
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.2.4"
|
||||
"php": ">=5.2.7"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/phpunit-bridge": "~2.7",
|
||||
"symfony/debug": "~2.7"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-0" : {
|
||||
|
|
@ -36,7 +40,7 @@
|
|||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.15-dev"
|
||||
"dev-master": "1.22-dev"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,30 +0,0 @@
|
|||
*.sw*
|
||||
.deps
|
||||
Makefile
|
||||
Makefile.fragments
|
||||
Makefile.global
|
||||
Makefile.objects
|
||||
acinclude.m4
|
||||
aclocal.m4
|
||||
build/
|
||||
config.cache
|
||||
config.guess
|
||||
config.h
|
||||
config.h.in
|
||||
config.log
|
||||
config.nice
|
||||
config.status
|
||||
config.sub
|
||||
configure
|
||||
configure.in
|
||||
install-sh
|
||||
libtool
|
||||
ltmain.sh
|
||||
missing
|
||||
mkinstalldirs
|
||||
run-tests.php
|
||||
twig.loT
|
||||
.libs/
|
||||
modules/
|
||||
twig.la
|
||||
twig.lo
|
||||
31
www/analytics/vendor/twig/twig/ext/twig/LICENSE
vendored
31
www/analytics/vendor/twig/twig/ext/twig/LICENSE
vendored
|
|
@ -1,31 +0,0 @@
|
|||
Copyright (c) 2009-2013 by the Twig Team, see AUTHORS for more details.
|
||||
|
||||
Some rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer in the documentation and/or other materials provided
|
||||
with the distribution.
|
||||
|
||||
* The names of the contributors may not be used to endorse or
|
||||
promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
|
@ -15,17 +15,21 @@
|
|||
#ifndef PHP_TWIG_H
|
||||
#define PHP_TWIG_H
|
||||
|
||||
#define PHP_TWIG_VERSION "1.15.1"
|
||||
#define PHP_TWIG_VERSION "1.22.3"
|
||||
|
||||
#include "php.h"
|
||||
|
||||
extern zend_module_entry twig_module_entry;
|
||||
#define phpext_twig_ptr &twig_module_entry
|
||||
#ifndef PHP_WIN32
|
||||
zend_module_entry *get_module(void);
|
||||
#endif
|
||||
|
||||
#ifdef ZTS
|
||||
#include "TSRM.h"
|
||||
#endif
|
||||
|
||||
PHP_FUNCTION(twig_template_get_attributes);
|
||||
PHP_RSHUTDOWN_FUNCTION(twig);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
248
www/analytics/vendor/twig/twig/ext/twig/twig.c
vendored
248
www/analytics/vendor/twig/twig/ext/twig/twig.c
vendored
|
|
@ -54,11 +54,22 @@ ZEND_BEGIN_ARG_INFO_EX(twig_template_get_attribute_args, ZEND_SEND_BY_VAL, ZEND_
|
|||
ZEND_ARG_INFO(0, isDefinedTest)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
zend_function_entry twig_functions[] = {
|
||||
#ifndef PHP_FE_END
|
||||
#define PHP_FE_END { NULL, NULL, NULL}
|
||||
#endif
|
||||
|
||||
static const zend_function_entry twig_functions[] = {
|
||||
PHP_FE(twig_template_get_attributes, twig_template_get_attribute_args)
|
||||
{NULL, NULL, NULL}
|
||||
PHP_FE_END
|
||||
};
|
||||
|
||||
PHP_RSHUTDOWN_FUNCTION(twig)
|
||||
{
|
||||
#if ZEND_DEBUG
|
||||
CG(unclean_shutdown) = 0; /* get rid of PHPUnit's exit() and report memleaks */
|
||||
#endif
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
zend_module_entry twig_module_entry = {
|
||||
STANDARD_MODULE_HEADER,
|
||||
|
|
@ -67,7 +78,7 @@ zend_module_entry twig_module_entry = {
|
|||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
PHP_RSHUTDOWN(twig),
|
||||
NULL,
|
||||
PHP_TWIG_VERSION,
|
||||
STANDARD_MODULE_PROPERTIES
|
||||
|
|
@ -78,7 +89,7 @@ zend_module_entry twig_module_entry = {
|
|||
ZEND_GET_MODULE(twig)
|
||||
#endif
|
||||
|
||||
int TWIG_ARRAY_KEY_EXISTS(zval *array, zval *key)
|
||||
static int TWIG_ARRAY_KEY_EXISTS(zval *array, zval *key)
|
||||
{
|
||||
if (Z_TYPE_P(array) != IS_ARRAY) {
|
||||
return 0;
|
||||
|
|
@ -100,7 +111,7 @@ int TWIG_ARRAY_KEY_EXISTS(zval *array, zval *key)
|
|||
}
|
||||
}
|
||||
|
||||
int TWIG_INSTANCE_OF(zval *object, zend_class_entry *interface TSRMLS_DC)
|
||||
static int TWIG_INSTANCE_OF(zval *object, zend_class_entry *interface TSRMLS_DC)
|
||||
{
|
||||
if (Z_TYPE_P(object) != IS_OBJECT) {
|
||||
return 0;
|
||||
|
|
@ -108,7 +119,7 @@ int TWIG_INSTANCE_OF(zval *object, zend_class_entry *interface TSRMLS_DC)
|
|||
return instanceof_function(Z_OBJCE_P(object), interface TSRMLS_CC);
|
||||
}
|
||||
|
||||
int TWIG_INSTANCE_OF_USERLAND(zval *object, char *interface TSRMLS_DC)
|
||||
static int TWIG_INSTANCE_OF_USERLAND(zval *object, char *interface TSRMLS_DC)
|
||||
{
|
||||
zend_class_entry **pce;
|
||||
if (Z_TYPE_P(object) != IS_OBJECT) {
|
||||
|
|
@ -120,7 +131,7 @@ int TWIG_INSTANCE_OF_USERLAND(zval *object, char *interface TSRMLS_DC)
|
|||
return instanceof_function(Z_OBJCE_P(object), *pce TSRMLS_CC);
|
||||
}
|
||||
|
||||
zval *TWIG_GET_ARRAYOBJECT_ELEMENT(zval *object, zval *offset TSRMLS_DC)
|
||||
static zval *TWIG_GET_ARRAYOBJECT_ELEMENT(zval *object, zval *offset TSRMLS_DC)
|
||||
{
|
||||
zend_class_entry *ce = Z_OBJCE_P(object);
|
||||
zval *retval;
|
||||
|
|
@ -143,7 +154,7 @@ zval *TWIG_GET_ARRAYOBJECT_ELEMENT(zval *object, zval *offset TSRMLS_DC)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
int TWIG_ISSET_ARRAYOBJECT_ELEMENT(zval *object, zval *offset TSRMLS_DC)
|
||||
static int TWIG_ISSET_ARRAYOBJECT_ELEMENT(zval *object, zval *offset TSRMLS_DC)
|
||||
{
|
||||
zend_class_entry *ce = Z_OBJCE_P(object);
|
||||
zval *retval;
|
||||
|
|
@ -166,7 +177,7 @@ int TWIG_ISSET_ARRAYOBJECT_ELEMENT(zval *object, zval *offset TSRMLS_DC)
|
|||
return 0;
|
||||
}
|
||||
|
||||
char *TWIG_STRTOLOWER(const char *str, int str_len)
|
||||
static char *TWIG_STRTOLOWER(const char *str, int str_len)
|
||||
{
|
||||
char *item_dup;
|
||||
|
||||
|
|
@ -175,7 +186,7 @@ char *TWIG_STRTOLOWER(const char *str, int str_len)
|
|||
return item_dup;
|
||||
}
|
||||
|
||||
zval *TWIG_CALL_USER_FUNC_ARRAY(zval *object, char *function, zval *arguments TSRMLS_DC)
|
||||
static zval *TWIG_CALL_USER_FUNC_ARRAY(zval *object, char *function, zval *arguments TSRMLS_DC)
|
||||
{
|
||||
zend_fcall_info fci;
|
||||
zval ***args = NULL;
|
||||
|
|
@ -227,7 +238,7 @@ zval *TWIG_CALL_USER_FUNC_ARRAY(zval *object, char *function, zval *arguments TS
|
|||
return retval_ptr;
|
||||
}
|
||||
|
||||
int TWIG_CALL_BOOLEAN(zval *object, char *functionName TSRMLS_DC)
|
||||
static int TWIG_CALL_BOOLEAN(zval *object, char *functionName TSRMLS_DC)
|
||||
{
|
||||
zval *ret;
|
||||
int res;
|
||||
|
|
@ -238,7 +249,7 @@ int TWIG_CALL_BOOLEAN(zval *object, char *functionName TSRMLS_DC)
|
|||
return res;
|
||||
}
|
||||
|
||||
zval *TWIG_GET_STATIC_PROPERTY(zval *class, char *prop_name TSRMLS_DC)
|
||||
static zval *TWIG_GET_STATIC_PROPERTY(zval *class, char *prop_name TSRMLS_DC)
|
||||
{
|
||||
zval **tmp_zval;
|
||||
zend_class_entry *ce;
|
||||
|
|
@ -256,7 +267,7 @@ zval *TWIG_GET_STATIC_PROPERTY(zval *class, char *prop_name TSRMLS_DC)
|
|||
return *tmp_zval;
|
||||
}
|
||||
|
||||
zval *TWIG_GET_ARRAY_ELEMENT_ZVAL(zval *class, zval *prop_name TSRMLS_DC)
|
||||
static zval *TWIG_GET_ARRAY_ELEMENT_ZVAL(zval *class, zval *prop_name TSRMLS_DC)
|
||||
{
|
||||
zval **tmp_zval;
|
||||
|
||||
|
|
@ -288,7 +299,7 @@ zval *TWIG_GET_ARRAY_ELEMENT_ZVAL(zval *class, zval *prop_name TSRMLS_DC)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
zval *TWIG_GET_ARRAY_ELEMENT(zval *class, char *prop_name, int prop_name_length TSRMLS_DC)
|
||||
static zval *TWIG_GET_ARRAY_ELEMENT(zval *class, char *prop_name, int prop_name_length TSRMLS_DC)
|
||||
{
|
||||
zval **tmp_zval;
|
||||
|
||||
|
|
@ -314,7 +325,7 @@ zval *TWIG_GET_ARRAY_ELEMENT(zval *class, char *prop_name, int prop_name_length
|
|||
return NULL;
|
||||
}
|
||||
|
||||
zval *TWIG_PROPERTY(zval *object, zval *propname TSRMLS_DC)
|
||||
static zval *TWIG_PROPERTY(zval *object, zval *propname TSRMLS_DC)
|
||||
{
|
||||
zval *tmp = NULL;
|
||||
|
||||
|
|
@ -331,7 +342,7 @@ zval *TWIG_PROPERTY(zval *object, zval *propname TSRMLS_DC)
|
|||
return tmp;
|
||||
}
|
||||
|
||||
int TWIG_HAS_PROPERTY(zval *object, zval *propname TSRMLS_DC)
|
||||
static int TWIG_HAS_PROPERTY(zval *object, zval *propname TSRMLS_DC)
|
||||
{
|
||||
if (Z_OBJ_HT_P(object)->has_property) {
|
||||
#if PHP_VERSION_ID >= 50400
|
||||
|
|
@ -343,7 +354,7 @@ int TWIG_HAS_PROPERTY(zval *object, zval *propname TSRMLS_DC)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int TWIG_HAS_DYNAMIC_PROPERTY(zval *object, char *prop, int prop_len TSRMLS_DC)
|
||||
static int TWIG_HAS_DYNAMIC_PROPERTY(zval *object, char *prop, int prop_len TSRMLS_DC)
|
||||
{
|
||||
if (Z_OBJ_HT_P(object)->get_properties) {
|
||||
return zend_hash_quick_exists(
|
||||
|
|
@ -356,7 +367,7 @@ int TWIG_HAS_DYNAMIC_PROPERTY(zval *object, char *prop, int prop_len TSRMLS_DC)
|
|||
return 0;
|
||||
}
|
||||
|
||||
zval *TWIG_PROPERTY_CHAR(zval *object, char *propname TSRMLS_DC)
|
||||
static zval *TWIG_PROPERTY_CHAR(zval *object, char *propname TSRMLS_DC)
|
||||
{
|
||||
zval *tmp_name_zval, *tmp;
|
||||
|
||||
|
|
@ -367,12 +378,7 @@ zval *TWIG_PROPERTY_CHAR(zval *object, char *propname TSRMLS_DC)
|
|||
return tmp;
|
||||
}
|
||||
|
||||
int TWIG_CALL_B_0(zval *object, char *method)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
zval *TWIG_CALL_S(zval *object, char *method, char *arg0 TSRMLS_DC)
|
||||
static zval *TWIG_CALL_S(zval *object, char *method, char *arg0 TSRMLS_DC)
|
||||
{
|
||||
zend_fcall_info fci;
|
||||
zval **args[1];
|
||||
|
|
@ -410,7 +416,7 @@ zval *TWIG_CALL_S(zval *object, char *method, char *arg0 TSRMLS_DC)
|
|||
return retval_ptr;
|
||||
}
|
||||
|
||||
int TWIG_CALL_SB(zval *object, char *method, char *arg0 TSRMLS_DC)
|
||||
static int TWIG_CALL_SB(zval *object, char *method, char *arg0 TSRMLS_DC)
|
||||
{
|
||||
zval *retval_ptr;
|
||||
int success;
|
||||
|
|
@ -425,51 +431,7 @@ int TWIG_CALL_SB(zval *object, char *method, char *arg0 TSRMLS_DC)
|
|||
return success;
|
||||
}
|
||||
|
||||
int TWIG_CALL_Z(zval *object, char *method, zval *arg1 TSRMLS_DC)
|
||||
{
|
||||
zend_fcall_info fci;
|
||||
zval **args[1];
|
||||
zval *zfunction;
|
||||
zval *retval_ptr;
|
||||
int success;
|
||||
|
||||
args[0] = &arg1;
|
||||
|
||||
MAKE_STD_ZVAL(zfunction);
|
||||
ZVAL_STRING(zfunction, method, 1);
|
||||
fci.size = sizeof(fci);
|
||||
fci.function_table = EG(function_table);
|
||||
fci.function_name = zfunction;
|
||||
fci.symbol_table = NULL;
|
||||
#if PHP_VERSION_ID >= 50300
|
||||
fci.object_ptr = object;
|
||||
#else
|
||||
fci.object_pp = &object;
|
||||
#endif
|
||||
fci.retval_ptr_ptr = &retval_ptr;
|
||||
fci.param_count = 1;
|
||||
fci.params = args;
|
||||
fci.no_separation = 0;
|
||||
|
||||
if (zend_call_function(&fci, NULL TSRMLS_CC) == FAILURE) {
|
||||
FREE_DTOR(zfunction);
|
||||
if (retval_ptr) {
|
||||
zval_ptr_dtor(&retval_ptr);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
FREE_DTOR(zfunction);
|
||||
|
||||
success = (retval_ptr && (Z_TYPE_P(retval_ptr) == IS_BOOL) && Z_LVAL_P(retval_ptr));
|
||||
if (retval_ptr) {
|
||||
zval_ptr_dtor(&retval_ptr);
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
int TWIG_CALL_ZZ(zval *object, char *method, zval *arg1, zval *arg2 TSRMLS_DC)
|
||||
static int TWIG_CALL_ZZ(zval *object, char *method, zval *arg1, zval *arg2 TSRMLS_DC)
|
||||
{
|
||||
zend_fcall_info fci;
|
||||
zval **args[2];
|
||||
|
|
@ -516,7 +478,7 @@ int TWIG_CALL_ZZ(zval *object, char *method, zval *arg1, zval *arg2 TSRMLS_DC)
|
|||
# define Z_UNSET_ISREF_P(pz) pz->is_ref = 0
|
||||
#endif
|
||||
|
||||
void TWIG_NEW(zval *object, char *class, zval *arg0, zval *arg1 TSRMLS_DC)
|
||||
static void TWIG_NEW(zval *object, char *class, zval *arg0, zval *arg1 TSRMLS_DC)
|
||||
{
|
||||
zend_class_entry **pce;
|
||||
|
||||
|
|
@ -561,7 +523,7 @@ static int twig_add_array_key_to_string(void *pDest APPLY_TSRMLS_DC, int num_arg
|
|||
return 0;
|
||||
}
|
||||
|
||||
char *TWIG_IMPLODE_ARRAY_KEYS(char *joiner, zval *array TSRMLS_DC)
|
||||
static char *TWIG_IMPLODE_ARRAY_KEYS(char *joiner, zval *array TSRMLS_DC)
|
||||
{
|
||||
smart_str collector = { 0, 0, 0 };
|
||||
|
||||
|
|
@ -572,24 +534,6 @@ char *TWIG_IMPLODE_ARRAY_KEYS(char *joiner, zval *array TSRMLS_DC)
|
|||
return collector.c;
|
||||
}
|
||||
|
||||
static void TWIG_THROW_EXCEPTION(char *exception_name TSRMLS_DC, char *message, ...)
|
||||
{
|
||||
char *buffer;
|
||||
va_list args;
|
||||
zend_class_entry **pce;
|
||||
|
||||
if (zend_lookup_class(exception_name, strlen(exception_name), &pce TSRMLS_CC) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
va_start(args, message);
|
||||
vspprintf(&buffer, 0, message, args);
|
||||
va_end(args);
|
||||
|
||||
zend_throw_exception_ex(*pce, 0 TSRMLS_CC, buffer);
|
||||
efree(buffer);
|
||||
}
|
||||
|
||||
static void TWIG_RUNTIME_ERROR(zval *template TSRMLS_DC, char *message, ...)
|
||||
{
|
||||
char *buffer;
|
||||
|
|
@ -665,6 +609,7 @@ static char *TWIG_GET_CLASS_NAME(zval *object TSRMLS_DC)
|
|||
|
||||
static int twig_add_method_to_class(void *pDest APPLY_TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
|
||||
{
|
||||
zend_class_entry *ce;
|
||||
zval *retval;
|
||||
char *item;
|
||||
size_t item_len;
|
||||
|
|
@ -675,12 +620,23 @@ static int twig_add_method_to_class(void *pDest APPLY_TSRMLS_DC, int num_args, v
|
|||
return 0;
|
||||
}
|
||||
|
||||
ce = *va_arg(args, zend_class_entry**);
|
||||
retval = va_arg(args, zval*);
|
||||
|
||||
item_len = strlen(mptr->common.function_name);
|
||||
item = estrndup(mptr->common.function_name, item_len);
|
||||
php_strtolower(item, item_len);
|
||||
|
||||
if (strcmp("getenvironment", item) == 0) {
|
||||
zend_class_entry **twig_template_ce;
|
||||
if (zend_lookup_class("Twig_Template", strlen("Twig_Template"), &twig_template_ce TSRMLS_CC) == FAILURE) {
|
||||
return 0;
|
||||
}
|
||||
if (instanceof_function(ce, *twig_template_ce TSRMLS_CC)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
add_assoc_stringl_ex(retval, item, item_len+1, item, item_len, 0);
|
||||
|
||||
return 0;
|
||||
|
|
@ -726,7 +682,7 @@ static void twig_add_class_to_cache(zval *cache, zval *object, char *class_name
|
|||
array_init(class_methods);
|
||||
array_init(class_properties);
|
||||
// add all methods to self::cache[$class]['methods']
|
||||
zend_hash_apply_with_arguments(&class_ce->function_table APPLY_TSRMLS_CC, twig_add_method_to_class, 1, class_methods);
|
||||
zend_hash_apply_with_arguments(&class_ce->function_table APPLY_TSRMLS_CC, twig_add_method_to_class, 2, &class_ce, class_methods);
|
||||
zend_hash_apply_with_arguments(&class_ce->properties_info APPLY_TSRMLS_CC, twig_add_property_to_class, 2, &class_ce, class_properties);
|
||||
|
||||
add_assoc_zval(class_info, "methods", class_methods);
|
||||
|
|
@ -794,6 +750,7 @@ PHP_FUNCTION(twig_template_get_attributes)
|
|||
) {
|
||||
|
||||
if (isDefinedTest) {
|
||||
efree(item);
|
||||
RETURN_TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -806,6 +763,7 @@ PHP_FUNCTION(twig_template_get_attributes)
|
|||
if (free_ret) {
|
||||
zval_ptr_dtor(&ret);
|
||||
}
|
||||
efree(item);
|
||||
return;
|
||||
}
|
||||
/*
|
||||
|
|
@ -819,9 +777,11 @@ PHP_FUNCTION(twig_template_get_attributes)
|
|||
*/
|
||||
if (strcmp("array", type) == 0 || Z_TYPE_P(object) != IS_OBJECT) {
|
||||
if (isDefinedTest) {
|
||||
efree(item);
|
||||
RETURN_FALSE;
|
||||
}
|
||||
if (ignoreStrictCheck || !TWIG_CALL_BOOLEAN(TWIG_PROPERTY_CHAR(template, "env" TSRMLS_CC), "isStrictVariables" TSRMLS_CC)) {
|
||||
efree(item);
|
||||
return;
|
||||
}
|
||||
/*
|
||||
|
|
@ -830,9 +790,19 @@ PHP_FUNCTION(twig_template_get_attributes)
|
|||
} elseif (is_object($object)) {
|
||||
$message = sprintf('Impossible to access a key "%s" on an object of class "%s" that does not implement ArrayAccess interface', $item, get_class($object));
|
||||
} elseif (is_array($object)) {
|
||||
$message = sprintf('Key "%s" for array with keys "%s" does not exist', $arrayItem, implode(', ', array_keys($object)));
|
||||
if (empty($object)) {
|
||||
$message = sprintf('Key "%s" does not exist as the array is empty', $arrayItem);
|
||||
} else {
|
||||
$message = sprintf('Key "%s" for array with keys "%s" does not exist', $arrayItem, implode(', ', array_keys($object)));
|
||||
}
|
||||
} elseif (Twig_Template::ARRAY_CALL === $type) {
|
||||
$message = sprintf('Impossible to access a key ("%s") on a %s variable ("%s")', $item, gettype($object), $object);
|
||||
if (null === $object) {
|
||||
$message = sprintf('Impossible to access a key ("%s") on a null variable', $item);
|
||||
} else {
|
||||
$message = sprintf('Impossible to access a key ("%s") on a %s variable ("%s")', $item, gettype($object), $object);
|
||||
}
|
||||
} elseif (null === $object) {
|
||||
$message = sprintf('Impossible to access an attribute ("%s") on a null variable', $item);
|
||||
} else {
|
||||
$message = sprintf('Impossible to access an attribute ("%s") on a %s variable ("%s")', $item, gettype($object), $object);
|
||||
}
|
||||
|
|
@ -845,18 +815,34 @@ PHP_FUNCTION(twig_template_get_attributes)
|
|||
} else if (Z_TYPE_P(object) == IS_OBJECT) {
|
||||
TWIG_RUNTIME_ERROR(template TSRMLS_CC, "Impossible to access a key \"%s\" on an object of class \"%s\" that does not implement ArrayAccess interface", item, TWIG_GET_CLASS_NAME(object TSRMLS_CC));
|
||||
} else if (Z_TYPE_P(object) == IS_ARRAY) {
|
||||
TWIG_RUNTIME_ERROR(template TSRMLS_CC, "Key \"%s\" for array with keys \"%s\" does not exist", item, TWIG_IMPLODE_ARRAY_KEYS(", ", object TSRMLS_CC));
|
||||
if (0 == zend_hash_num_elements(Z_ARRVAL_P(object))) {
|
||||
TWIG_RUNTIME_ERROR(template TSRMLS_CC, "Key \"%s\" does not exist as the array is empty", item);
|
||||
} else {
|
||||
char *array_keys = TWIG_IMPLODE_ARRAY_KEYS(", ", object TSRMLS_CC);
|
||||
TWIG_RUNTIME_ERROR(template TSRMLS_CC, "Key \"%s\" for array with keys \"%s\" does not exist", item, array_keys);
|
||||
efree(array_keys);
|
||||
}
|
||||
} else {
|
||||
char *type_name = zend_zval_type_name(object);
|
||||
Z_ADDREF_P(object);
|
||||
convert_to_string(object);
|
||||
TWIG_RUNTIME_ERROR(template TSRMLS_CC,
|
||||
(strcmp("array", type) == 0)
|
||||
? "Impossible to access a key (\"%s\") on a %s variable (\"%s\")"
|
||||
: "Impossible to access an attribute (\"%s\") on a %s variable (\"%s\")",
|
||||
item, type_name, Z_STRVAL_P(object));
|
||||
if (Z_TYPE_P(object) == IS_NULL) {
|
||||
convert_to_string(object);
|
||||
TWIG_RUNTIME_ERROR(template TSRMLS_CC,
|
||||
(strcmp("array", type) == 0)
|
||||
? "Impossible to access a key (\"%s\") on a %s variable"
|
||||
: "Impossible to access an attribute (\"%s\") on a %s variable",
|
||||
item, type_name);
|
||||
} else {
|
||||
convert_to_string(object);
|
||||
TWIG_RUNTIME_ERROR(template TSRMLS_CC,
|
||||
(strcmp("array", type) == 0)
|
||||
? "Impossible to access a key (\"%s\") on a %s variable (\"%s\")"
|
||||
: "Impossible to access an attribute (\"%s\") on a %s variable (\"%s\")",
|
||||
item, type_name, Z_STRVAL_P(object));
|
||||
}
|
||||
zval_ptr_dtor(&object);
|
||||
}
|
||||
efree(item);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -870,27 +856,42 @@ PHP_FUNCTION(twig_template_get_attributes)
|
|||
|
||||
if (Z_TYPE_P(object) != IS_OBJECT) {
|
||||
if (isDefinedTest) {
|
||||
efree(item);
|
||||
RETURN_FALSE;
|
||||
}
|
||||
/*
|
||||
if ($ignoreStrictCheck || !$this->env->isStrictVariables()) {
|
||||
return null;
|
||||
}
|
||||
throw new Twig_Error_Runtime(sprintf('Impossible to invoke a method ("%s") on a %s variable ("%s")', $item, gettype($object), $object), -1, $this->getTemplateName());
|
||||
|
||||
if (null === $object) {
|
||||
$message = sprintf('Impossible to invoke a method ("%s") on a null variable', $item);
|
||||
} else {
|
||||
$message = sprintf('Impossible to invoke a method ("%s") on a %s variable ("%s")', $item, gettype($object), $object);
|
||||
}
|
||||
|
||||
throw new Twig_Error_Runtime($message, -1, $this->getTemplateName());
|
||||
}
|
||||
*/
|
||||
if (ignoreStrictCheck || !TWIG_CALL_BOOLEAN(TWIG_PROPERTY_CHAR(template, "env" TSRMLS_CC), "isStrictVariables" TSRMLS_CC)) {
|
||||
efree(item);
|
||||
return;
|
||||
}
|
||||
|
||||
type_name = zend_zval_type_name(object);
|
||||
Z_ADDREF_P(object);
|
||||
convert_to_string_ex(&object);
|
||||
if (Z_TYPE_P(object) == IS_NULL) {
|
||||
convert_to_string_ex(&object);
|
||||
|
||||
TWIG_RUNTIME_ERROR(template TSRMLS_CC, "Impossible to invoke a method (\"%s\") on a %s variable (\"%s\")", item, type_name, Z_STRVAL_P(object));
|
||||
TWIG_RUNTIME_ERROR(template TSRMLS_CC, "Impossible to invoke a method (\"%s\") on a %s variable", item, type_name);
|
||||
} else {
|
||||
convert_to_string_ex(&object);
|
||||
|
||||
TWIG_RUNTIME_ERROR(template TSRMLS_CC, "Impossible to invoke a method (\"%s\") on a %s variable (\"%s\")", item, type_name, Z_STRVAL_P(object));
|
||||
}
|
||||
|
||||
zval_ptr_dtor(&object);
|
||||
|
||||
efree(item);
|
||||
return;
|
||||
}
|
||||
/*
|
||||
|
|
@ -909,7 +910,7 @@ PHP_FUNCTION(twig_template_get_attributes)
|
|||
|
||||
/*
|
||||
// object property
|
||||
if (Twig_Template::METHOD_CALL !== $type) {
|
||||
if (Twig_Template::METHOD_CALL !== $type && !$object instanceof Twig_Template) {
|
||||
if (isset($object->$item) || array_key_exists((string) $item, $object)) {
|
||||
if ($isDefinedTest) {
|
||||
return true;
|
||||
|
|
@ -923,7 +924,7 @@ PHP_FUNCTION(twig_template_get_attributes)
|
|||
}
|
||||
}
|
||||
*/
|
||||
if (strcmp("method", type) != 0) {
|
||||
if (strcmp("method", type) != 0 && !TWIG_INSTANCE_OF_USERLAND(object, "Twig_Template" TSRMLS_CC)) {
|
||||
zval *tmp_properties, *tmp_item;
|
||||
|
||||
tmp_properties = TWIG_GET_ARRAY_ELEMENT(tmp_class, "properties", strlen("properties") TSRMLS_CC);
|
||||
|
|
@ -931,23 +932,42 @@ PHP_FUNCTION(twig_template_get_attributes)
|
|||
|
||||
if (tmp_item || TWIG_HAS_PROPERTY(object, zitem TSRMLS_CC) || TWIG_HAS_DYNAMIC_PROPERTY(object, item, item_len TSRMLS_CC)) {
|
||||
if (isDefinedTest) {
|
||||
efree(item);
|
||||
RETURN_TRUE;
|
||||
}
|
||||
if (TWIG_CALL_SB(TWIG_PROPERTY_CHAR(template, "env" TSRMLS_CC), "hasExtension", "sandbox" TSRMLS_CC)) {
|
||||
TWIG_CALL_ZZ(TWIG_CALL_S(TWIG_PROPERTY_CHAR(template, "env" TSRMLS_CC), "getExtension", "sandbox" TSRMLS_CC), "checkPropertyAllowed", object, zitem TSRMLS_CC);
|
||||
}
|
||||
if (EG(exception)) {
|
||||
efree(item);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = TWIG_PROPERTY(object, zitem TSRMLS_CC);
|
||||
efree(item);
|
||||
RETURN_ZVAL(ret, 1, 0);
|
||||
}
|
||||
}
|
||||
/*
|
||||
// object method
|
||||
if (!isset(self::$cache[$class]['methods'])) {
|
||||
self::$cache[$class]['methods'] = array_change_key_case(array_flip(get_class_methods($object)));
|
||||
if ($object instanceof self) {
|
||||
$ref = new ReflectionClass($class);
|
||||
$methods = array();
|
||||
|
||||
foreach ($ref->getMethods(ReflectionMethod::IS_PUBLIC) as $refMethod) {
|
||||
$methodName = strtolower($refMethod->name);
|
||||
|
||||
// Accessing the environment from templates is forbidden to prevent untrusted changes to the environment
|
||||
if ('getenvironment' !== $methodName) {
|
||||
$methods[$methodName] = true;
|
||||
}
|
||||
}
|
||||
|
||||
self::$cache[$class]['methods'] = $methods;
|
||||
} else {
|
||||
self::$cache[$class]['methods'] = array_change_key_case(array_flip(get_class_methods($object)));
|
||||
}
|
||||
}
|
||||
|
||||
$call = false;
|
||||
|
|
@ -1013,19 +1033,22 @@ PHP_FUNCTION(twig_template_get_attributes)
|
|||
efree(lcItem);
|
||||
|
||||
if (isDefinedTest) {
|
||||
efree(item);
|
||||
RETURN_FALSE;
|
||||
}
|
||||
if (ignoreStrictCheck || !TWIG_CALL_BOOLEAN(TWIG_PROPERTY_CHAR(template, "env" TSRMLS_CC), "isStrictVariables" TSRMLS_CC)) {
|
||||
efree(item);
|
||||
return;
|
||||
}
|
||||
TWIG_RUNTIME_ERROR(template TSRMLS_CC, "Method \"%s\" for object \"%s\" does not exist", item, TWIG_GET_CLASS_NAME(object TSRMLS_CC));
|
||||
efree(item);
|
||||
return;
|
||||
}
|
||||
|
||||
if (isDefinedTest) {
|
||||
efree(tmp_method_name_get);
|
||||
efree(tmp_method_name_is);
|
||||
efree(lcItem);
|
||||
efree(lcItem);efree(item);
|
||||
RETURN_TRUE;
|
||||
}
|
||||
/*
|
||||
|
|
@ -1038,11 +1061,11 @@ PHP_FUNCTION(twig_template_get_attributes)
|
|||
if (TWIG_CALL_SB(TWIG_PROPERTY_CHAR(template, "env" TSRMLS_CC), "hasExtension", "sandbox" TSRMLS_CC)) {
|
||||
TWIG_CALL_ZZ(TWIG_CALL_S(TWIG_PROPERTY_CHAR(template, "env" TSRMLS_CC), "getExtension", "sandbox" TSRMLS_CC), "checkMethodAllowed", object, zmethod TSRMLS_CC);
|
||||
}
|
||||
zval_ptr_dtor(&zmethod);
|
||||
if (EG(exception)) {
|
||||
efree(tmp_method_name_get);
|
||||
efree(tmp_method_name_is);
|
||||
efree(lcItem);
|
||||
zval_ptr_dtor(&zmethod);
|
||||
efree(lcItem);efree(item);
|
||||
return;
|
||||
}
|
||||
/*
|
||||
|
|
@ -1060,6 +1083,9 @@ PHP_FUNCTION(twig_template_get_attributes)
|
|||
ret = TWIG_CALL_USER_FUNC_ARRAY(object, method, arguments TSRMLS_CC);
|
||||
if (EG(exception) && TWIG_INSTANCE_OF(EG(exception), spl_ce_BadMethodCallException TSRMLS_CC)) {
|
||||
if (ignoreStrictCheck || !TWIG_CALL_BOOLEAN(TWIG_PROPERTY_CHAR(template, "env" TSRMLS_CC), "isStrictVariables" TSRMLS_CC)) {
|
||||
efree(tmp_method_name_get);
|
||||
efree(tmp_method_name_is);
|
||||
efree(lcItem);efree(item);
|
||||
zend_clear_exception(TSRMLS_C);
|
||||
return;
|
||||
}
|
||||
|
|
@ -1068,7 +1094,6 @@ PHP_FUNCTION(twig_template_get_attributes)
|
|||
efree(tmp_method_name_get);
|
||||
efree(tmp_method_name_is);
|
||||
efree(lcItem);
|
||||
zval_ptr_dtor(&zmethod);
|
||||
}
|
||||
/*
|
||||
// useful when calling a template method from a template
|
||||
|
|
@ -1079,6 +1104,7 @@ PHP_FUNCTION(twig_template_get_attributes)
|
|||
|
||||
return $ret;
|
||||
*/
|
||||
efree(item);
|
||||
// ret can be null, if e.g. the called method throws an exception
|
||||
if (ret) {
|
||||
if (TWIG_INSTANCE_OF_USERLAND(object, "Twig_TemplateInterface" TSRMLS_CC)) {
|
||||
|
|
|
|||
|
|
@ -9,24 +9,30 @@
|
|||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
@trigger_error('The Twig_Autoloader class is deprecated and will be removed in 2.0. Use Composer instead.', E_USER_DEPRECATED);
|
||||
|
||||
/**
|
||||
* Autoloads Twig classes.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @deprecated Use Composer instead. Will be removed in Twig 2.0.
|
||||
*/
|
||||
class Twig_Autoloader
|
||||
{
|
||||
/**
|
||||
* Registers Twig_Autoloader as an SPL autoloader.
|
||||
*
|
||||
* @param Boolean $prepend Whether to prepend the autoloader or not.
|
||||
* @param bool $prepend Whether to prepend the autoloader or not.
|
||||
*/
|
||||
public static function register($prepend = false)
|
||||
{
|
||||
if (version_compare(phpversion(), '5.3.0', '>=')) {
|
||||
spl_autoload_register(array(__CLASS__, 'autoload'), true, $prepend);
|
||||
} else {
|
||||
@trigger_error('Using Twig_Autoloader is deprecated. Use Composer instead.', E_USER_DEPRECATED);
|
||||
|
||||
if (PHP_VERSION_ID < 50300) {
|
||||
spl_autoload_register(array(__CLASS__, 'autoload'));
|
||||
} else {
|
||||
spl_autoload_register(array(__CLASS__, 'autoload'), true, $prepend);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
62
www/analytics/vendor/twig/twig/lib/Twig/BaseNodeVisitor.php
vendored
Normal file
62
www/analytics/vendor/twig/twig/lib/Twig/BaseNodeVisitor.php
vendored
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Twig_BaseNodeVisitor can be used to make node visitors compatible with Twig 1.x and 2.x.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
abstract class Twig_BaseNodeVisitor implements Twig_NodeVisitorInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
final public function enterNode(Twig_NodeInterface $node, Twig_Environment $env)
|
||||
{
|
||||
if (!$node instanceof Twig_Node) {
|
||||
throw new LogicException('Twig_BaseNodeVisitor only supports Twig_Node instances.');
|
||||
}
|
||||
|
||||
return $this->doEnterNode($node, $env);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
final public function leaveNode(Twig_NodeInterface $node, Twig_Environment $env)
|
||||
{
|
||||
if (!$node instanceof Twig_Node) {
|
||||
throw new LogicException('Twig_BaseNodeVisitor only supports Twig_Node instances.');
|
||||
}
|
||||
|
||||
return $this->doLeaveNode($node, $env);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called before child nodes are visited.
|
||||
*
|
||||
* @param Twig_Node $node The node to visit
|
||||
* @param Twig_Environment $env The Twig environment instance
|
||||
*
|
||||
* @return Twig_Node The modified node
|
||||
*/
|
||||
abstract protected function doEnterNode(Twig_Node $node, Twig_Environment $env);
|
||||
|
||||
/**
|
||||
* Called after child nodes are visited.
|
||||
*
|
||||
* @param Twig_Node $node The node to visit
|
||||
* @param Twig_Environment $env The Twig environment instance
|
||||
*
|
||||
* @return Twig_Node|false The modified node or false if the node must be removed
|
||||
*/
|
||||
abstract protected function doLeaveNode(Twig_Node $node, Twig_Environment $env);
|
||||
}
|
||||
96
www/analytics/vendor/twig/twig/lib/Twig/Cache/Filesystem.php
vendored
Normal file
96
www/analytics/vendor/twig/twig/lib/Twig/Cache/Filesystem.php
vendored
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2015 Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements a cache on the filesystem.
|
||||
*
|
||||
* @author Andrew Tch <andrew@noop.lv>
|
||||
*/
|
||||
class Twig_Cache_Filesystem implements Twig_CacheInterface
|
||||
{
|
||||
const FORCE_BYTECODE_INVALIDATION = 1;
|
||||
|
||||
private $directory;
|
||||
private $options;
|
||||
|
||||
/**
|
||||
* @param $directory string The root cache directory
|
||||
* @param $options int A set of options
|
||||
*/
|
||||
public function __construct($directory, $options = 0)
|
||||
{
|
||||
$this->directory = $directory;
|
||||
$this->options = $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function generateKey($name, $className)
|
||||
{
|
||||
$hash = hash('sha256', $className);
|
||||
|
||||
return $this->directory.'/'.$hash[0].$hash[1].'/'.$hash.'.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function load($key)
|
||||
{
|
||||
@include_once $key;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function write($key, $content)
|
||||
{
|
||||
$dir = dirname($key);
|
||||
if (!is_dir($dir)) {
|
||||
if (false === @mkdir($dir, 0777, true) && !is_dir($dir)) {
|
||||
throw new RuntimeException(sprintf('Unable to create the cache directory (%s).', $dir));
|
||||
}
|
||||
} elseif (!is_writable($dir)) {
|
||||
throw new RuntimeException(sprintf('Unable to write in the cache directory (%s).', $dir));
|
||||
}
|
||||
|
||||
$tmpFile = tempnam($dir, basename($key));
|
||||
if (false !== @file_put_contents($tmpFile, $content) && @rename($tmpFile, $key)) {
|
||||
@chmod($key, 0666 & ~umask());
|
||||
|
||||
if (self::FORCE_BYTECODE_INVALIDATION == ($this->options & self::FORCE_BYTECODE_INVALIDATION)) {
|
||||
// Compile cached file into bytecode cache
|
||||
if (function_exists('opcache_invalidate')) {
|
||||
opcache_invalidate($key, true);
|
||||
} elseif (function_exists('apc_compile_file')) {
|
||||
apc_compile_file($key);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
throw new RuntimeException(sprintf('Failed to write cache file "%s".', $key));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getTimestamp($key)
|
||||
{
|
||||
if (!file_exists($key)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (int) @filemtime($key);
|
||||
}
|
||||
}
|
||||
48
www/analytics/vendor/twig/twig/lib/Twig/Cache/Null.php
vendored
Normal file
48
www/analytics/vendor/twig/twig/lib/Twig/Cache/Null.php
vendored
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2015 Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements a no-cache strategy.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class Twig_Cache_Null implements Twig_CacheInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function generateKey($name, $className)
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function write($key, $content)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function load($key)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getTimestamp($key)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
56
www/analytics/vendor/twig/twig/lib/Twig/CacheInterface.php
vendored
Normal file
56
www/analytics/vendor/twig/twig/lib/Twig/CacheInterface.php
vendored
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2015 Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Interface implemented by cache classes.
|
||||
*
|
||||
* It is highly recommended to always store templates on the filesystem to
|
||||
* benefit from the PHP opcode cache. This interface is mostly useful if you
|
||||
* need to implement a custom strategy for storing templates on the filesystem.
|
||||
*
|
||||
* @author Andrew Tch <andrew@noop.lv>
|
||||
*/
|
||||
interface Twig_CacheInterface
|
||||
{
|
||||
/**
|
||||
* Generates a cache key for the given template class name.
|
||||
*
|
||||
* @param string $name The template name
|
||||
* @param string $className The template class name
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function generateKey($name, $className);
|
||||
|
||||
/**
|
||||
* Writes the compiled template to cache.
|
||||
*
|
||||
* @param string $key The cache key
|
||||
* @param string $content The template representation as a PHP class
|
||||
*/
|
||||
public function write($key, $content);
|
||||
|
||||
/**
|
||||
* Loads a template from the cache.
|
||||
*
|
||||
* @param string $key The cache key
|
||||
*/
|
||||
public function load($key);
|
||||
|
||||
/**
|
||||
* Returns the modification timestamp of a key.
|
||||
*
|
||||
* @param string $key The cache key
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getTimestamp($key);
|
||||
}
|
||||
|
|
@ -21,7 +21,7 @@ class Twig_Compiler implements Twig_CompilerInterface
|
|||
protected $source;
|
||||
protected $indentation;
|
||||
protected $env;
|
||||
protected $debugInfo;
|
||||
protected $debugInfo = array();
|
||||
protected $sourceOffset;
|
||||
protected $sourceLine;
|
||||
protected $filename;
|
||||
|
|
@ -34,7 +34,6 @@ class Twig_Compiler implements Twig_CompilerInterface
|
|||
public function __construct(Twig_Environment $env)
|
||||
{
|
||||
$this->env = $env;
|
||||
$this->debugInfo = array();
|
||||
}
|
||||
|
||||
public function getFilename()
|
||||
|
|
@ -66,7 +65,7 @@ class Twig_Compiler implements Twig_CompilerInterface
|
|||
* Compiles a node.
|
||||
*
|
||||
* @param Twig_NodeInterface $node The node to compile
|
||||
* @param integer $indentation The current indentation
|
||||
* @param int $indentation The current indentation
|
||||
*
|
||||
* @return Twig_Compiler The current compiler instance
|
||||
*/
|
||||
|
|
@ -74,6 +73,7 @@ class Twig_Compiler implements Twig_CompilerInterface
|
|||
{
|
||||
$this->lastLine = null;
|
||||
$this->source = '';
|
||||
$this->debugInfo = array();
|
||||
$this->sourceOffset = 0;
|
||||
// source code starts at 1 (as we then increment it when we encounter new lines)
|
||||
$this->sourceLine = 1;
|
||||
|
|
@ -181,14 +181,14 @@ class Twig_Compiler implements Twig_CompilerInterface
|
|||
} elseif (is_array($value)) {
|
||||
$this->raw('array(');
|
||||
$first = true;
|
||||
foreach ($value as $key => $value) {
|
||||
foreach ($value as $key => $v) {
|
||||
if (!$first) {
|
||||
$this->raw(', ');
|
||||
}
|
||||
$first = false;
|
||||
$this->repr($key);
|
||||
$this->raw(' => ');
|
||||
$this->repr($value);
|
||||
$this->repr($v);
|
||||
}
|
||||
$this->raw(')');
|
||||
} else {
|
||||
|
|
@ -230,13 +230,15 @@ class Twig_Compiler implements Twig_CompilerInterface
|
|||
|
||||
public function getDebugInfo()
|
||||
{
|
||||
ksort($this->debugInfo);
|
||||
|
||||
return $this->debugInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indents the generated code.
|
||||
*
|
||||
* @param integer $step The number of indentation to add
|
||||
* @param int $step The number of indentation to add
|
||||
*
|
||||
* @return Twig_Compiler The current compiler instance
|
||||
*/
|
||||
|
|
@ -250,7 +252,7 @@ class Twig_Compiler implements Twig_CompilerInterface
|
|||
/**
|
||||
* Outdents the generated code.
|
||||
*
|
||||
* @param integer $step The number of indentation to remove
|
||||
* @param int $step The number of indentation to remove
|
||||
*
|
||||
* @return Twig_Compiler The current compiler instance
|
||||
*
|
||||
|
|
@ -267,4 +269,9 @@ class Twig_Compiler implements Twig_CompilerInterface
|
|||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getVarName()
|
||||
{
|
||||
return sprintf('__internal_%s', hash('sha256', uniqid(mt_rand(), true), false));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,8 @@
|
|||
* Interface implemented by compiler classes.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @deprecated since 1.12 (to be removed in 2.0)
|
||||
*
|
||||
* @deprecated since 1.12 (to be removed in 3.0)
|
||||
*/
|
||||
interface Twig_CompilerInterface
|
||||
{
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
*/
|
||||
class Twig_Environment
|
||||
{
|
||||
const VERSION = '1.15.1';
|
||||
const VERSION = '1.22.3';
|
||||
|
||||
protected $charset;
|
||||
protected $loader;
|
||||
|
|
@ -34,17 +34,22 @@ class Twig_Environment
|
|||
protected $tests;
|
||||
protected $functions;
|
||||
protected $globals;
|
||||
protected $runtimeInitialized;
|
||||
protected $extensionInitialized;
|
||||
protected $runtimeInitialized = false;
|
||||
protected $extensionInitialized = false;
|
||||
protected $loadedTemplates;
|
||||
protected $strictVariables;
|
||||
protected $unaryOperators;
|
||||
protected $binaryOperators;
|
||||
protected $templateClassPrefix = '__TwigTemplate_';
|
||||
protected $functionCallbacks;
|
||||
protected $filterCallbacks;
|
||||
protected $functionCallbacks = array();
|
||||
protected $filterCallbacks = array();
|
||||
protected $staging;
|
||||
|
||||
private $originalCache;
|
||||
private $bcWriteCacheFile = false;
|
||||
private $bcGetCacheFilename = false;
|
||||
private $lastModifiedExtension = 0;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
|
|
@ -58,8 +63,9 @@ class Twig_Environment
|
|||
* * base_template_class: The base template class to use for generated
|
||||
* templates (default to Twig_Template).
|
||||
*
|
||||
* * cache: An absolute path where to store the compiled templates, or
|
||||
* false to disable compilation cache (default).
|
||||
* * cache: An absolute path where to store the compiled templates,
|
||||
* a Twig_Cache_Interface implementation,
|
||||
* or false to disable compilation cache (default).
|
||||
*
|
||||
* * auto_reload: Whether to reload the template if the original source changed.
|
||||
* If you don't provide the auto_reload option, it will be
|
||||
|
|
@ -72,6 +78,7 @@ class Twig_Environment
|
|||
* * false: disable auto-escaping
|
||||
* * true: equivalent to html
|
||||
* * html, js: set the autoescaping to one of the supported strategies
|
||||
* * filename: set the autoescaping strategy based on the template filename extension
|
||||
* * PHP callback: a PHP callback that returns an escaping strategy based on the template "filename"
|
||||
*
|
||||
* * optimizations: A flag that indicates which optimizations to apply
|
||||
|
|
@ -85,34 +92,49 @@ class Twig_Environment
|
|||
{
|
||||
if (null !== $loader) {
|
||||
$this->setLoader($loader);
|
||||
} else {
|
||||
@trigger_error('Not passing a Twig_LoaderInterface as the first constructor argument of Twig_Environment is deprecated.', E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
$options = array_merge(array(
|
||||
'debug' => false,
|
||||
'charset' => 'UTF-8',
|
||||
'debug' => false,
|
||||
'charset' => 'UTF-8',
|
||||
'base_template_class' => 'Twig_Template',
|
||||
'strict_variables' => false,
|
||||
'autoescape' => 'html',
|
||||
'cache' => false,
|
||||
'auto_reload' => null,
|
||||
'optimizations' => -1,
|
||||
'strict_variables' => false,
|
||||
'autoescape' => 'html',
|
||||
'cache' => false,
|
||||
'auto_reload' => null,
|
||||
'optimizations' => -1,
|
||||
), $options);
|
||||
|
||||
$this->debug = (bool) $options['debug'];
|
||||
$this->charset = strtoupper($options['charset']);
|
||||
$this->baseTemplateClass = $options['base_template_class'];
|
||||
$this->autoReload = null === $options['auto_reload'] ? $this->debug : (bool) $options['auto_reload'];
|
||||
$this->strictVariables = (bool) $options['strict_variables'];
|
||||
$this->runtimeInitialized = false;
|
||||
$this->debug = (bool) $options['debug'];
|
||||
$this->charset = strtoupper($options['charset']);
|
||||
$this->baseTemplateClass = $options['base_template_class'];
|
||||
$this->autoReload = null === $options['auto_reload'] ? $this->debug : (bool) $options['auto_reload'];
|
||||
$this->strictVariables = (bool) $options['strict_variables'];
|
||||
$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();
|
||||
|
||||
// For BC
|
||||
if (is_string($this->originalCache)) {
|
||||
$r = new ReflectionMethod($this, 'writeCacheFile');
|
||||
if ($r->getDeclaringClass()->getName() !== __CLASS__) {
|
||||
@trigger_error('The Twig_Environment::writeCacheFile method is deprecated and will be removed in Twig 2.0.', E_USER_DEPRECATED);
|
||||
|
||||
$this->bcWriteCacheFile = true;
|
||||
}
|
||||
|
||||
$r = new ReflectionMethod($this, 'getCacheFilename');
|
||||
if ($r->getDeclaringClass()->getName() !== __CLASS__) {
|
||||
@trigger_error('The Twig_Environment::getCacheFilename method is deprecated and will be removed in Twig 2.0.', E_USER_DEPRECATED);
|
||||
|
||||
$this->bcGetCacheFilename = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -154,7 +176,7 @@ class Twig_Environment
|
|||
/**
|
||||
* Checks if debug mode is enabled.
|
||||
*
|
||||
* @return Boolean true if debug mode is enabled, false otherwise
|
||||
* @return bool true if debug mode is enabled, false otherwise
|
||||
*/
|
||||
public function isDebug()
|
||||
{
|
||||
|
|
@ -180,7 +202,7 @@ class Twig_Environment
|
|||
/**
|
||||
* Checks if the auto_reload option is enabled.
|
||||
*
|
||||
* @return Boolean true if auto_reload is enabled, false otherwise
|
||||
* @return bool true if auto_reload is enabled, false otherwise
|
||||
*/
|
||||
public function isAutoReload()
|
||||
{
|
||||
|
|
@ -206,7 +228,7 @@ class Twig_Environment
|
|||
/**
|
||||
* Checks if the strict_variables option is enabled.
|
||||
*
|
||||
* @return Boolean true if strict_variables is enabled, false otherwise
|
||||
* @return bool true if strict_variables is enabled, false otherwise
|
||||
*/
|
||||
public function isStrictVariables()
|
||||
{
|
||||
|
|
@ -214,24 +236,43 @@ class Twig_Environment
|
|||
}
|
||||
|
||||
/**
|
||||
* Gets the cache directory or false if cache is disabled.
|
||||
* Gets the current cache implementation.
|
||||
*
|
||||
* @return string|false
|
||||
* @param bool $original Whether to return the original cache option or the real cache instance
|
||||
*
|
||||
* @return Twig_CacheInterface|string|false A Twig_CacheInterface implementation,
|
||||
* an absolute path to the compiled templates,
|
||||
* or false to disable cache
|
||||
*/
|
||||
public function getCache()
|
||||
public function getCache($original = true)
|
||||
{
|
||||
return $this->cache;
|
||||
return $original ? $this->originalCache : $this->cache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the cache directory or false if cache is disabled.
|
||||
*
|
||||
* @param string|false $cache The absolute path to the compiled templates,
|
||||
* or false to disable cache
|
||||
*/
|
||||
/**
|
||||
* Sets the current cache implementation.
|
||||
*
|
||||
* @param Twig_CacheInterface|string|false $cache A Twig_CacheInterface implementation,
|
||||
* an absolute path to the compiled templates,
|
||||
* or false to disable cache
|
||||
*/
|
||||
public function setCache($cache)
|
||||
{
|
||||
$this->cache = $cache ? $cache : false;
|
||||
if (is_string($cache)) {
|
||||
$this->originalCache = $cache;
|
||||
$this->cache = new Twig_Cache_Filesystem($cache);
|
||||
} elseif (false === $cache) {
|
||||
$this->originalCache = $cache;
|
||||
$this->cache = new Twig_Cache_Null();
|
||||
} elseif (null === $cache) {
|
||||
@trigger_error('Using "null" as the cache strategy is deprecated and will be removed in Twig 2.0.', E_USER_DEPRECATED);
|
||||
$this->originalCache = false;
|
||||
$this->cache = new Twig_Cache_Null();
|
||||
} elseif ($cache instanceof Twig_CacheInterface) {
|
||||
$this->originalCache = $this->cache = $cache;
|
||||
} else {
|
||||
throw new LogicException(sprintf('Cache can only be a string, false, or a Twig_CacheInterface implementation.'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -240,38 +281,52 @@ class Twig_Environment
|
|||
* @param string $name The template name
|
||||
*
|
||||
* @return string|false The cache file name or false when caching is disabled
|
||||
*
|
||||
* @deprecated since 1.22 (to be removed in 2.0)
|
||||
*/
|
||||
public function getCacheFilename($name)
|
||||
{
|
||||
if (false === $this->cache) {
|
||||
return false;
|
||||
}
|
||||
@trigger_error(sprintf('The %s method is deprecated and will be removed in Twig 2.0.', __METHOD__), E_USER_DEPRECATED);
|
||||
|
||||
$class = substr($this->getTemplateClass($name), strlen($this->templateClassPrefix));
|
||||
$key = $this->cache->generateKey($name, $this->getTemplateClass($name));
|
||||
|
||||
return $this->getCache().'/'.substr($class, 0, 2).'/'.substr($class, 2, 2).'/'.substr($class, 4).'.php';
|
||||
return !$key ? false : $key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the template class associated with the given string.
|
||||
*
|
||||
* @param string $name The name for which to calculate the template class name
|
||||
* @param integer $index The index if it is an embedded template
|
||||
* The generated template class is based on the following parameters:
|
||||
*
|
||||
* * The cache key for the given template;
|
||||
* * The currently enabled extensions;
|
||||
* * Whether the Twig C extension is available or not.
|
||||
*
|
||||
* @param string $name The name for which to calculate the template class name
|
||||
* @param int|null $index The index if it is an embedded template
|
||||
*
|
||||
* @return string The template class name
|
||||
*/
|
||||
public function getTemplateClass($name, $index = null)
|
||||
{
|
||||
return $this->templateClassPrefix.hash('sha256', $this->getLoader()->getCacheKey($name)).(null === $index ? '' : '_'.$index);
|
||||
$key = $this->getLoader()->getCacheKey($name);
|
||||
$key .= json_encode(array_keys($this->extensions));
|
||||
$key .= function_exists('twig_template_get_attributes');
|
||||
|
||||
return $this->templateClassPrefix.hash('sha256', $key).(null === $index ? '' : '_'.$index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the template class prefix.
|
||||
*
|
||||
* @return string The template class prefix
|
||||
*
|
||||
* @deprecated since 1.22 (to be removed in 2.0)
|
||||
*/
|
||||
public function getTemplateClassPrefix()
|
||||
{
|
||||
@trigger_error(sprintf('The %s method is deprecated and will be removed in Twig 2.0.', __METHOD__), E_USER_DEPRECATED);
|
||||
|
||||
return $this->templateClassPrefix;
|
||||
}
|
||||
|
||||
|
|
@ -310,8 +365,8 @@ class Twig_Environment
|
|||
/**
|
||||
* Loads a template by name.
|
||||
*
|
||||
* @param string $name The template name
|
||||
* @param integer $index The index if it is an embedded template
|
||||
* @param string $name The template name
|
||||
* @param int $index The index if it is an embedded template
|
||||
*
|
||||
* @return Twig_TemplateInterface A template instance representing the given template name
|
||||
*
|
||||
|
|
@ -327,14 +382,25 @@ class Twig_Environment
|
|||
}
|
||||
|
||||
if (!class_exists($cls, false)) {
|
||||
if (false === $cache = $this->getCacheFilename($name)) {
|
||||
eval('?>'.$this->compileSource($this->getLoader()->getSource($name), $name));
|
||||
if ($this->bcGetCacheFilename) {
|
||||
$key = $this->getCacheFilename($name);
|
||||
} else {
|
||||
if (!is_file($cache) || ($this->isAutoReload() && !$this->isTemplateFresh($name, filemtime($cache)))) {
|
||||
$this->writeCacheFile($cache, $this->compileSource($this->getLoader()->getSource($name), $name));
|
||||
$key = $this->cache->generateKey($name, $cls);
|
||||
}
|
||||
|
||||
if (!$this->isAutoReload() || $this->isTemplateFresh($name, $this->cache->getTimestamp($key))) {
|
||||
$this->cache->load($key);
|
||||
}
|
||||
|
||||
if (!class_exists($cls, false)) {
|
||||
$content = $this->compileSource($this->getLoader()->getSource($name), $name);
|
||||
if ($this->bcWriteCacheFile) {
|
||||
$this->writeCacheFile($key, $content);
|
||||
} else {
|
||||
$this->cache->write($key, $content);
|
||||
}
|
||||
|
||||
require_once $cache;
|
||||
eval('?>'.$content);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -345,6 +411,40 @@ class Twig_Environment
|
|||
return $this->loadedTemplates[$cls] = new $cls($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a template from source.
|
||||
*
|
||||
* This method should not be used as a generic way to load templates.
|
||||
*
|
||||
* @param string $template The template name
|
||||
*
|
||||
* @return Twig_Template A template instance representing the given template name
|
||||
*
|
||||
* @throws Twig_Error_Loader When the template cannot be found
|
||||
* @throws Twig_Error_Syntax When an error occurred during compilation
|
||||
*/
|
||||
public function createTemplate($template)
|
||||
{
|
||||
$name = sprintf('__string_template__%s', hash('sha256', uniqid(mt_rand(), true), false));
|
||||
|
||||
$loader = new Twig_Loader_Chain(array(
|
||||
new Twig_Loader_Array(array($name => $template)),
|
||||
$current = $this->getLoader(),
|
||||
));
|
||||
|
||||
$this->setLoader($loader);
|
||||
try {
|
||||
$template = $this->loadTemplate($name);
|
||||
} catch (Exception $e) {
|
||||
$this->setLoader($current);
|
||||
|
||||
throw $e;
|
||||
}
|
||||
$this->setLoader($current);
|
||||
|
||||
return $template;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the template is still fresh.
|
||||
*
|
||||
|
|
@ -352,21 +452,14 @@ class Twig_Environment
|
|||
* this method also checks if the enabled extensions have
|
||||
* not changed.
|
||||
*
|
||||
* @param string $name The template name
|
||||
* @param timestamp $time The last modification time of the cached template
|
||||
* @param string $name The template name
|
||||
* @param int $time The last modification time of the cached template
|
||||
*
|
||||
* @return Boolean true if the template is fresh, false otherwise
|
||||
* @return bool true if the template is fresh, false otherwise
|
||||
*/
|
||||
public function isTemplateFresh($name, $time)
|
||||
{
|
||||
foreach ($this->extensions as $extension) {
|
||||
$r = new ReflectionObject($extension);
|
||||
if (filemtime($r->getFileName()) > $time) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->getLoader()->isFresh($name, $time);
|
||||
return $this->lastModifiedExtension <= $time && $this->getLoader()->isFresh($name, $time);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -408,24 +501,30 @@ class Twig_Environment
|
|||
|
||||
/**
|
||||
* Clears the internal template cache.
|
||||
*
|
||||
* @deprecated since 1.18.3 (to be removed in 2.0)
|
||||
*/
|
||||
public function clearTemplateCache()
|
||||
{
|
||||
@trigger_error(sprintf('The %s method is deprecated and will be removed in Twig 2.0.', __METHOD__), E_USER_DEPRECATED);
|
||||
|
||||
$this->loadedTemplates = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the template cache files on the filesystem.
|
||||
*
|
||||
* @deprecated since 1.22 (to be removed in 2.0)
|
||||
*/
|
||||
public function clearCacheFiles()
|
||||
{
|
||||
if (false === $this->cache) {
|
||||
return;
|
||||
}
|
||||
@trigger_error(sprintf('The %s method is deprecated and will be removed in Twig 2.0.', __METHOD__), E_USER_DEPRECATED);
|
||||
|
||||
foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($this->cache), RecursiveIteratorIterator::LEAVES_ONLY) as $file) {
|
||||
if ($file->isFile()) {
|
||||
@unlink($file->getPathname());
|
||||
if (is_string($this->originalCache)) {
|
||||
foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($this->originalCache), RecursiveIteratorIterator::LEAVES_ONLY) as $file) {
|
||||
if ($file->isFile()) {
|
||||
@unlink($file->getPathname());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -447,7 +546,7 @@ class Twig_Environment
|
|||
/**
|
||||
* Sets the Lexer instance.
|
||||
*
|
||||
* @param Twig_LexerInterface A Twig_LexerInterface instance
|
||||
* @param Twig_LexerInterface $lexer A Twig_LexerInterface instance
|
||||
*/
|
||||
public function setLexer(Twig_LexerInterface $lexer)
|
||||
{
|
||||
|
|
@ -486,7 +585,7 @@ class Twig_Environment
|
|||
/**
|
||||
* Sets the Parser instance.
|
||||
*
|
||||
* @param Twig_ParserInterface A Twig_ParserInterface instance
|
||||
* @param Twig_ParserInterface $parser A Twig_ParserInterface instance
|
||||
*/
|
||||
public function setParser(Twig_ParserInterface $parser)
|
||||
{
|
||||
|
|
@ -556,7 +655,13 @@ class Twig_Environment
|
|||
public function compileSource($source, $name = null)
|
||||
{
|
||||
try {
|
||||
return $this->compile($this->parse($this->tokenize($source, $name)));
|
||||
$compiled = $this->compile($this->parse($this->tokenize($source, $name)), $source);
|
||||
|
||||
if (isset($source[0])) {
|
||||
$compiled .= '/* '.str_replace(array('*/', "\r\n", "\r", "\n"), array('*//* ', "\n", "\n", "*/\n/* "), $source)."*/\n";
|
||||
}
|
||||
|
||||
return $compiled;
|
||||
} catch (Twig_Error $e) {
|
||||
$e->setTemplateFile($name);
|
||||
throw $e;
|
||||
|
|
@ -626,7 +731,7 @@ class Twig_Environment
|
|||
*
|
||||
* @param string $name The extension name
|
||||
*
|
||||
* @return Boolean Whether the extension is registered or not
|
||||
* @return bool Whether the extension is registered or not
|
||||
*/
|
||||
public function hasExtension($name)
|
||||
{
|
||||
|
|
@ -660,6 +765,11 @@ class Twig_Environment
|
|||
throw new LogicException(sprintf('Unable to register extension "%s" as extensions have already been initialized.', $extension->getName()));
|
||||
}
|
||||
|
||||
$r = new ReflectionObject($extension);
|
||||
if (($extensionTime = filemtime($r->getFileName())) > $this->lastModifiedExtension) {
|
||||
$this->lastModifiedExtension = $extensionTime;
|
||||
}
|
||||
|
||||
$this->extensions[$extension->getName()] = $extension;
|
||||
}
|
||||
|
||||
|
|
@ -674,6 +784,8 @@ class Twig_Environment
|
|||
*/
|
||||
public function removeExtension($name)
|
||||
{
|
||||
@trigger_error(sprintf('The %s method is deprecated and will be removed in Twig 2.0.', __METHOD__), E_USER_DEPRECATED);
|
||||
|
||||
if ($this->extensionInitialized) {
|
||||
throw new LogicException(sprintf('Unable to remove extension "%s" as extensions have already been initialized.', $name));
|
||||
}
|
||||
|
|
@ -793,6 +905,8 @@ class Twig_Environment
|
|||
if ($name instanceof Twig_SimpleFilter) {
|
||||
$filter = $name;
|
||||
$name = $filter->getName();
|
||||
} else {
|
||||
@trigger_error(sprintf('Passing a name as a first argument to the %s method is deprecated. Pass an instance of "Twig_SimpleFilter" instead when defining filter "%s".', __METHOD__, $name), E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
if ($this->extensionInitialized) {
|
||||
|
|
@ -882,6 +996,8 @@ class Twig_Environment
|
|||
if ($name instanceof Twig_SimpleTest) {
|
||||
$test = $name;
|
||||
$name = $test->getName();
|
||||
} else {
|
||||
@trigger_error(sprintf('Passing a name as a first argument to the %s method is deprecated. Pass an instance of "Twig_SimpleTest" instead when defining test "%s".', __METHOD__, $name), E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
if ($this->extensionInitialized) {
|
||||
|
|
@ -940,6 +1056,8 @@ class Twig_Environment
|
|||
if ($name instanceof Twig_SimpleFunction) {
|
||||
$function = $name;
|
||||
$name = $function->getName();
|
||||
} else {
|
||||
@trigger_error(sprintf('Passing a name as a first argument to the %s method is deprecated. Pass an instance of "Twig_SimpleFunction" instead when defining function "%s".', __METHOD__, $name), E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
if ($this->extensionInitialized) {
|
||||
|
|
@ -1030,11 +1148,11 @@ class Twig_Environment
|
|||
$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));
|
||||
// The deprecation notice must be turned into the following exception in Twig 2.0
|
||||
@trigger_error(sprintf('Registering global variable "%s" at runtime or when the extensions have already been initialized is deprecated.', $name), E_USER_DEPRECATED);
|
||||
//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) {
|
||||
|
|
@ -1149,7 +1267,7 @@ class Twig_Environment
|
|||
}
|
||||
|
||||
$this->extensionInitialized = true;
|
||||
$this->parsers = new Twig_TokenParserBroker();
|
||||
$this->parsers = new Twig_TokenParserBroker(array(), array(), false);
|
||||
$this->filters = array();
|
||||
$this->functions = array();
|
||||
$this->tests = array();
|
||||
|
|
@ -1167,11 +1285,10 @@ class Twig_Environment
|
|||
{
|
||||
// filters
|
||||
foreach ($extension->getFilters() as $name => $filter) {
|
||||
if ($name instanceof Twig_SimpleFilter) {
|
||||
$filter = $name;
|
||||
$name = $filter->getName();
|
||||
} elseif ($filter instanceof Twig_SimpleFilter) {
|
||||
if ($filter instanceof Twig_SimpleFilter) {
|
||||
$name = $filter->getName();
|
||||
} else {
|
||||
@trigger_error(sprintf('Using an instance of "%s" for filter "%s" is deprecated. Use Twig_SimpleFilter instead.', get_class($filter), $name), E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
$this->filters[$name] = $filter;
|
||||
|
|
@ -1179,11 +1296,10 @@ class Twig_Environment
|
|||
|
||||
// functions
|
||||
foreach ($extension->getFunctions() as $name => $function) {
|
||||
if ($name instanceof Twig_SimpleFunction) {
|
||||
$function = $name;
|
||||
$name = $function->getName();
|
||||
} elseif ($function instanceof Twig_SimpleFunction) {
|
||||
if ($function instanceof Twig_SimpleFunction) {
|
||||
$name = $function->getName();
|
||||
} else {
|
||||
@trigger_error(sprintf('Using an instance of "%s" for function "%s" is deprecated. Use Twig_SimpleFunction instead.', get_class($function), $name), E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
$this->functions[$name] = $function;
|
||||
|
|
@ -1191,11 +1307,10 @@ class Twig_Environment
|
|||
|
||||
// tests
|
||||
foreach ($extension->getTests() as $name => $test) {
|
||||
if ($name instanceof Twig_SimpleTest) {
|
||||
$test = $name;
|
||||
$name = $test->getName();
|
||||
} elseif ($test instanceof Twig_SimpleTest) {
|
||||
if ($test instanceof Twig_SimpleTest) {
|
||||
$name = $test->getName();
|
||||
} else {
|
||||
@trigger_error(sprintf('Using an instance of "%s" for test "%s" is deprecated. Use Twig_SimpleTest instead.', get_class($test), $name), E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
$this->tests[$name] = $test;
|
||||
|
|
@ -1206,6 +1321,8 @@ class Twig_Environment
|
|||
if ($parser instanceof Twig_TokenParserInterface) {
|
||||
$this->parsers->addTokenParser($parser);
|
||||
} elseif ($parser instanceof Twig_TokenParserBrokerInterface) {
|
||||
@trigger_error('Registering a Twig_TokenParserBrokerInterface instance is deprecated.', E_USER_DEPRECATED);
|
||||
|
||||
$this->parsers->addTokenParserBroker($parser);
|
||||
} else {
|
||||
throw new LogicException('getTokenParsers() must return an array of Twig_TokenParserInterface or Twig_TokenParserBrokerInterface instances');
|
||||
|
|
@ -1228,27 +1345,11 @@ class Twig_Environment
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated since 1.22 (to be removed in 2.0)
|
||||
*/
|
||||
protected function writeCacheFile($file, $content)
|
||||
{
|
||||
$dir = dirname($file);
|
||||
if (!is_dir($dir)) {
|
||||
if (false === @mkdir($dir, 0777, true) && !is_dir($dir)) {
|
||||
throw new RuntimeException(sprintf("Unable to create the cache directory (%s).", $dir));
|
||||
}
|
||||
} elseif (!is_writable($dir)) {
|
||||
throw new RuntimeException(sprintf("Unable to write in the cache directory (%s).", $dir));
|
||||
}
|
||||
|
||||
$tmpFile = tempnam($dir, basename($file));
|
||||
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, 0666 & ~umask());
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
throw new RuntimeException(sprintf('Failed to write cache file "%s".', $file));
|
||||
$this->cache->write($file, $content);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,13 +51,13 @@ class Twig_Error extends Exception
|
|||
* By default, automatic guessing is enabled.
|
||||
*
|
||||
* @param string $message The error message
|
||||
* @param integer $lineno The template line where the error occurred
|
||||
* @param int $lineno The template line where the error occurred
|
||||
* @param string $filename The template file name where the error occurred
|
||||
* @param Exception $previous The previous exception
|
||||
*/
|
||||
public function __construct($message, $lineno = -1, $filename = null, Exception $previous = null)
|
||||
{
|
||||
if (version_compare(PHP_VERSION, '5.3.0', '<')) {
|
||||
if (PHP_VERSION_ID < 50300) {
|
||||
$this->previous = $previous;
|
||||
parent::__construct('');
|
||||
} else {
|
||||
|
|
@ -111,7 +111,7 @@ class Twig_Error extends Exception
|
|||
/**
|
||||
* Gets the template line where the error occurred.
|
||||
*
|
||||
* @return integer The template line
|
||||
* @return int The template line
|
||||
*/
|
||||
public function getTemplateLine()
|
||||
{
|
||||
|
|
@ -121,7 +121,7 @@ class Twig_Error extends Exception
|
|||
/**
|
||||
* Sets the template line where the error occurred.
|
||||
*
|
||||
* @param integer $lineno The template line
|
||||
* @param int $lineno The template line
|
||||
*/
|
||||
public function setTemplateLine($lineno)
|
||||
{
|
||||
|
|
@ -188,7 +188,7 @@ class Twig_Error extends Exception
|
|||
$template = null;
|
||||
$templateClass = null;
|
||||
|
||||
if (version_compare(phpversion(), '5.3.6', '>=')) {
|
||||
if (PHP_VERSION_ID >= 50306) {
|
||||
$backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS | DEBUG_BACKTRACE_PROVIDE_OBJECT);
|
||||
} else {
|
||||
$backtrace = debug_backtrace();
|
||||
|
|
@ -229,6 +229,8 @@ class Twig_Error extends Exception
|
|||
|
||||
while ($e = array_pop($exceptions)) {
|
||||
$traces = $e->getTrace();
|
||||
array_unshift($traces, array('file' => $e->getFile(), 'line' => $e->getLine()));
|
||||
|
||||
while ($trace = array_shift($traces)) {
|
||||
if (!isset($trace['file']) || !isset($trace['line']) || $file != $trace['file']) {
|
||||
continue;
|
||||
|
|
|
|||
|
|
@ -13,7 +13,8 @@
|
|||
* Adds an exists() method for loaders.
|
||||
*
|
||||
* @author Florin Patan <florinpatan@gmail.com>
|
||||
* @deprecated since 1.12 (to be removed in 2.0)
|
||||
*
|
||||
* @deprecated since 1.12 (to be removed in 3.0)
|
||||
*/
|
||||
interface Twig_ExistsLoaderInterface
|
||||
{
|
||||
|
|
@ -22,7 +23,7 @@ interface Twig_ExistsLoaderInterface
|
|||
*
|
||||
* @param string $name The name of the template to check if we can load
|
||||
*
|
||||
* @return Boolean If the template source code is handled by this loader or not
|
||||
* @return bool If the template source code is handled by this loader or not
|
||||
*/
|
||||
public function exists($name);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -164,6 +164,21 @@ class Twig_ExpressionParser
|
|||
$this->parser->getStream()->next();
|
||||
$node = new Twig_Node_Expression_Name($token->getValue(), $token->getLine());
|
||||
break;
|
||||
} elseif (isset($this->unaryOperators[$token->getValue()])) {
|
||||
$class = $this->unaryOperators[$token->getValue()]['class'];
|
||||
|
||||
$ref = new ReflectionClass($class);
|
||||
$negClass = 'Twig_Node_Expression_Unary_Neg';
|
||||
$posClass = 'Twig_Node_Expression_Unary_Pos';
|
||||
if (!(in_array($ref->getName(), array($negClass, $posClass)) || $ref->isSubclassOf($negClass) || $ref->isSubclassOf($posClass))) {
|
||||
throw new Twig_Error_Syntax(sprintf('Unexpected unary operator "%s"', $token->getValue()), $token->getLine(), $this->parser->getFilename());
|
||||
}
|
||||
|
||||
$this->parser->getStream()->next();
|
||||
$expr = $this->parsePrimaryExpression();
|
||||
|
||||
$node = new $class($expr, $token->getLine());
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
|
|
@ -300,7 +315,7 @@ class Twig_ExpressionParser
|
|||
{
|
||||
switch ($name) {
|
||||
case 'parent':
|
||||
$args = $this->parseArguments();
|
||||
$this->parseArguments();
|
||||
if (!count($this->parser->getBlockStack())) {
|
||||
throw new Twig_Error_Syntax('Calling "parent" outside a block is forbidden', $line, $this->parser->getFilename());
|
||||
}
|
||||
|
|
@ -318,7 +333,7 @@ class Twig_ExpressionParser
|
|||
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_Template::ANY_CALL, $line);
|
||||
return new Twig_Node_Expression_GetAttr($args->getNode(0), $args->getNode(1), count($args) > 2 ? $args->getNode(2) : null, Twig_Template::ANY_CALL, $line);
|
||||
default:
|
||||
if (null !== $alias = $this->parser->getImportedSymbol('function', $name)) {
|
||||
$arguments = new Twig_Node_Expression_Array(array(), $line);
|
||||
|
|
@ -372,7 +387,13 @@ class Twig_ExpressionParser
|
|||
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);
|
||||
$name = $arg->getAttribute('value');
|
||||
|
||||
if ($this->parser->isReservedMacroName($name)) {
|
||||
throw new Twig_Error_Syntax(sprintf('"%s" cannot be called as macro as it is a reserved keyword', $name), $token->getLine(), $this->parser->getFilename());
|
||||
}
|
||||
|
||||
$node = new Twig_Node_Expression_MethodCall($node, 'get'.$name, $arguments, $lineno);
|
||||
$node->setAttribute('safe', true);
|
||||
|
||||
return $node;
|
||||
|
|
@ -451,8 +472,12 @@ class Twig_ExpressionParser
|
|||
/**
|
||||
* Parses arguments.
|
||||
*
|
||||
* @param Boolean $namedArguments Whether to allow named arguments or not
|
||||
* @param Boolean $definition Whether we are parsing arguments for a function definition
|
||||
* @param bool $namedArguments Whether to allow named arguments or not
|
||||
* @param bool $definition Whether we are parsing arguments for a function definition
|
||||
*
|
||||
* @return Twig_Node
|
||||
*
|
||||
* @throws Twig_Error_Syntax
|
||||
*/
|
||||
public function parseArguments($namedArguments = false, $definition = false)
|
||||
{
|
||||
|
|
@ -553,6 +578,16 @@ class Twig_ExpressionParser
|
|||
throw new Twig_Error_Syntax($message, $line, $this->parser->getFilename());
|
||||
}
|
||||
|
||||
if ($function instanceof Twig_SimpleFunction && $function->isDeprecated()) {
|
||||
$message = sprintf('Twig Function "%s" is deprecated', $function->getName());
|
||||
if ($function->getAlternative()) {
|
||||
$message .= sprintf('. Use "%s" instead', $function->getAlternative());
|
||||
}
|
||||
$message .= sprintf(' in %s at line %d.', $this->parser->getFilename(), $line);
|
||||
|
||||
@trigger_error($message, E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
if ($function instanceof Twig_SimpleFunction) {
|
||||
return $function->getNodeClass();
|
||||
}
|
||||
|
|
@ -573,6 +608,16 @@ class Twig_ExpressionParser
|
|||
throw new Twig_Error_Syntax($message, $line, $this->parser->getFilename());
|
||||
}
|
||||
|
||||
if ($filter instanceof Twig_SimpleFilter && $filter->isDeprecated()) {
|
||||
$message = sprintf('Twig Filter "%s" is deprecated', $filter->getName());
|
||||
if ($filter->getAlternative()) {
|
||||
$message .= sprintf('. Use "%s" instead', $filter->getAlternative());
|
||||
}
|
||||
$message .= sprintf(' in %s at line %d.', $this->parser->getFilename(), $line);
|
||||
|
||||
@trigger_error($message, E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
if ($filter instanceof Twig_SimpleFilter) {
|
||||
return $filter->getNodeClass();
|
||||
}
|
||||
|
|
@ -583,7 +628,9 @@ class Twig_ExpressionParser
|
|||
// checks that the node only contains "constant" elements
|
||||
protected function checkConstantExpression(Twig_NodeInterface $node)
|
||||
{
|
||||
if (!($node instanceof Twig_Node_Expression_Constant || $node instanceof Twig_Node_Expression_Array)) {
|
||||
if (!($node instanceof Twig_Node_Expression_Constant || $node instanceof Twig_Node_Expression_Array
|
||||
|| $node instanceof Twig_Node_Expression_Unary_Neg || $node instanceof Twig_Node_Expression_Unary_Pos
|
||||
)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,20 +11,14 @@
|
|||
abstract class Twig_Extension implements Twig_ExtensionInterface
|
||||
{
|
||||
/**
|
||||
* Initializes the runtime environment.
|
||||
*
|
||||
* This is where you can load some file that contains filter functions for instance.
|
||||
*
|
||||
* @param Twig_Environment $environment The current Twig_Environment instance
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
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
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getTokenParsers()
|
||||
{
|
||||
|
|
@ -32,9 +26,7 @@ abstract class Twig_Extension implements Twig_ExtensionInterface
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns the node visitor instances to add to the existing list.
|
||||
*
|
||||
* @return Twig_NodeVisitorInterface[] An array of Twig_NodeVisitorInterface instances
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getNodeVisitors()
|
||||
{
|
||||
|
|
@ -42,9 +34,7 @@ abstract class Twig_Extension implements Twig_ExtensionInterface
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns a list of filters to add to the existing list.
|
||||
*
|
||||
* @return array An array of filters
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFilters()
|
||||
{
|
||||
|
|
@ -52,9 +42,7 @@ abstract class Twig_Extension implements Twig_ExtensionInterface
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns a list of tests to add to the existing list.
|
||||
*
|
||||
* @return array An array of tests
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getTests()
|
||||
{
|
||||
|
|
@ -62,9 +50,7 @@ abstract class Twig_Extension implements Twig_ExtensionInterface
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns a list of functions to add to the existing list.
|
||||
*
|
||||
* @return array An array of functions
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFunctions()
|
||||
{
|
||||
|
|
@ -72,9 +58,7 @@ abstract class Twig_Extension implements Twig_ExtensionInterface
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns a list of operators to add to the existing list.
|
||||
*
|
||||
* @return array An array of operators
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getOperators()
|
||||
{
|
||||
|
|
@ -82,9 +66,7 @@ abstract class Twig_Extension implements Twig_ExtensionInterface
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns a list of global variables to add to the existing list.
|
||||
*
|
||||
* @return array An array of global variables
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getGlobals()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -95,9 +95,9 @@ class Twig_Extension_Core extends Twig_Extension
|
|||
/**
|
||||
* 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 int $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)
|
||||
{
|
||||
|
|
@ -152,7 +152,7 @@ class Twig_Extension_Core extends Twig_Extension
|
|||
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('replace', 'twig_replace_filter'),
|
||||
new Twig_SimpleFilter('number_format', 'twig_number_format_filter', array('needs_environment' => true)),
|
||||
new Twig_SimpleFilter('abs', 'abs'),
|
||||
new Twig_SimpleFilter('round', 'twig_round'),
|
||||
|
|
@ -173,7 +173,7 @@ class Twig_Extension_Core extends Twig_Extension
|
|||
|
||||
// array helpers
|
||||
new Twig_SimpleFilter('join', 'twig_join_filter'),
|
||||
new Twig_SimpleFilter('split', 'twig_split_filter'),
|
||||
new Twig_SimpleFilter('split', 'twig_split_filter', array('needs_environment' => true)),
|
||||
new Twig_SimpleFilter('sort', 'twig_sort_filter'),
|
||||
new Twig_SimpleFilter('merge', 'twig_array_merge'),
|
||||
new Twig_SimpleFilter('batch', 'twig_array_batch'),
|
||||
|
|
@ -233,11 +233,11 @@ class Twig_Extension_Core extends Twig_Extension
|
|||
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('sameas', null, array('node_class' => 'Twig_Node_Expression_Test_Sameas', 'deprecated' => true, 'alternative' => 'same as')),
|
||||
new Twig_SimpleTest('same as', 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('divisibleby', null, array('node_class' => 'Twig_Node_Expression_Test_Divisibleby', 'deprecated' => true, 'alternative' => 'divisible by')),
|
||||
new Twig_SimpleTest('divisible by', 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'),
|
||||
|
|
@ -255,37 +255,37 @@ class Twig_Extension_Core extends Twig_Extension
|
|||
return array(
|
||||
array(
|
||||
'not' => array('precedence' => 50, 'class' => 'Twig_Node_Expression_Unary_Not'),
|
||||
'-' => array('precedence' => 500, 'class' => 'Twig_Node_Expression_Unary_Neg'),
|
||||
'+' => array('precedence' => 500, 'class' => 'Twig_Node_Expression_Unary_Pos'),
|
||||
'-' => array('precedence' => 500, 'class' => 'Twig_Node_Expression_Unary_Neg'),
|
||||
'+' => array('precedence' => 500, 'class' => 'Twig_Node_Expression_Unary_Pos'),
|
||||
),
|
||||
array(
|
||||
'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),
|
||||
'>' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_Greater', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
||||
'>=' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_GreaterEqual', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
||||
'<=' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_LessEqual', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
||||
'not in' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_NotIn', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
||||
'in' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_In', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
||||
'matches' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_Matches', '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),
|
||||
'>' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_Greater', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
||||
'>=' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_GreaterEqual', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
||||
'<=' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_LessEqual', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
||||
'not in' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_NotIn', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
||||
'in' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_In', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
||||
'matches' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_Matches', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
||||
'starts with' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_StartsWith', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
||||
'ends with' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_EndsWith', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
||||
'..' => array('precedence' => 25, 'class' => 'Twig_Node_Expression_Binary_Range', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
||||
'+' => array('precedence' => 30, 'class' => 'Twig_Node_Expression_Binary_Add', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
||||
'-' => array('precedence' => 30, 'class' => 'Twig_Node_Expression_Binary_Sub', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
||||
'~' => array('precedence' => 40, 'class' => 'Twig_Node_Expression_Binary_Concat', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
||||
'*' => array('precedence' => 60, 'class' => 'Twig_Node_Expression_Binary_Mul', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
||||
'/' => array('precedence' => 60, 'class' => 'Twig_Node_Expression_Binary_Div', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
||||
'//' => array('precedence' => 60, 'class' => 'Twig_Node_Expression_Binary_FloorDiv', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
||||
'%' => array('precedence' => 60, 'class' => 'Twig_Node_Expression_Binary_Mod', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
||||
'is' => array('precedence' => 100, 'callable' => array($this, 'parseTestExpression'), 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
||||
'is not' => array('precedence' => 100, 'callable' => array($this, 'parseNotTestExpression'), 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
||||
'**' => array('precedence' => 200, 'class' => 'Twig_Node_Expression_Binary_Power', 'associativity' => Twig_ExpressionParser::OPERATOR_RIGHT),
|
||||
'ends with' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_EndsWith', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
||||
'..' => array('precedence' => 25, 'class' => 'Twig_Node_Expression_Binary_Range', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
||||
'+' => array('precedence' => 30, 'class' => 'Twig_Node_Expression_Binary_Add', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
||||
'-' => array('precedence' => 30, 'class' => 'Twig_Node_Expression_Binary_Sub', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
||||
'~' => array('precedence' => 40, 'class' => 'Twig_Node_Expression_Binary_Concat', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
||||
'*' => array('precedence' => 60, 'class' => 'Twig_Node_Expression_Binary_Mul', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
||||
'/' => array('precedence' => 60, 'class' => 'Twig_Node_Expression_Binary_Div', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
||||
'//' => array('precedence' => 60, 'class' => 'Twig_Node_Expression_Binary_FloorDiv', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
||||
'%' => array('precedence' => 60, 'class' => 'Twig_Node_Expression_Binary_Mod', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
||||
'is' => array('precedence' => 100, 'callable' => array($this, 'parseTestExpression'), 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
||||
'is not' => array('precedence' => 100, 'callable' => array($this, 'parseNotTestExpression'), 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT),
|
||||
'**' => array('precedence' => 200, 'class' => 'Twig_Node_Expression_Binary_Power', 'associativity' => Twig_ExpressionParser::OPERATOR_RIGHT),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
@ -298,8 +298,19 @@ class Twig_Extension_Core extends Twig_Extension
|
|||
public function parseTestExpression(Twig_Parser $parser, Twig_NodeInterface $node)
|
||||
{
|
||||
$stream = $parser->getStream();
|
||||
$name = $stream->expect(Twig_Token::NAME_TYPE)->getValue();
|
||||
$class = $this->getTestNodeClass($parser, $name, $node->getLine());
|
||||
list($name, $test) = $this->getTest($parser, $node->getLine());
|
||||
|
||||
if ($test instanceof Twig_SimpleTest && $test->isDeprecated()) {
|
||||
$message = sprintf('Twig Test "%s" is deprecated', $name);
|
||||
if ($test->getAlternative()) {
|
||||
$message .= sprintf('. Use "%s" instead', $test->getAlternative());
|
||||
}
|
||||
$message .= sprintf(' in %s at line %d.', $stream->getFilename(), $stream->getCurrent()->getLine());
|
||||
|
||||
@trigger_error($message, E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
$class = $this->getTestNodeClass($parser, $test);
|
||||
$arguments = null;
|
||||
if ($stream->test(Twig_Token::PUNCTUATION_TYPE, '(')) {
|
||||
$arguments = $parser->getExpressionParser()->parseArguments(true);
|
||||
|
|
@ -308,38 +319,42 @@ class Twig_Extension_Core extends Twig_Extension
|
|||
return new $class($node, $name, $arguments, $parser->getCurrentToken()->getLine());
|
||||
}
|
||||
|
||||
protected function getTestNodeClass(Twig_Parser $parser, $name, $line)
|
||||
protected function getTest(Twig_Parser $parser, $line)
|
||||
{
|
||||
$stream = $parser->getStream();
|
||||
$name = $stream->expect(Twig_Token::NAME_TYPE)->getValue();
|
||||
$env = $parser->getEnvironment();
|
||||
$testMap = $env->getTests();
|
||||
$testName = null;
|
||||
if (isset($testMap[$name])) {
|
||||
$testName = $name;
|
||||
} elseif ($parser->getStream()->test(Twig_Token::NAME_TYPE)) {
|
||||
|
||||
if ($test = $env->getTest($name)) {
|
||||
return array($name, $test);
|
||||
}
|
||||
|
||||
if ($stream->test(Twig_Token::NAME_TYPE)) {
|
||||
// try 2-words tests
|
||||
$name = $name.' '.$parser->getCurrentToken()->getValue();
|
||||
|
||||
if (isset($testMap[$name])) {
|
||||
if ($test = $env->getTest($name)) {
|
||||
$parser->getStream()->next();
|
||||
|
||||
$testName = $name;
|
||||
return array($name, $test);
|
||||
}
|
||||
}
|
||||
|
||||
if (null === $testName) {
|
||||
$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());
|
||||
$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));
|
||||
}
|
||||
|
||||
if ($testMap[$name] instanceof Twig_SimpleTest) {
|
||||
return $testMap[$name]->getNodeClass();
|
||||
throw new Twig_Error_Syntax($message, $line, $parser->getFilename());
|
||||
}
|
||||
|
||||
protected function getTestNodeClass(Twig_Parser $parser, $test)
|
||||
{
|
||||
if ($test instanceof Twig_SimpleTest) {
|
||||
return $test->getNodeClass();
|
||||
}
|
||||
|
||||
return $testMap[$name] instanceof Twig_Test_Node ? $testMap[$name]->getClass() : 'Twig_Node_Expression_Test';
|
||||
return $test instanceof Twig_Test_Node ? $test->getClass() : 'Twig_Node_Expression_Test';
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -357,7 +372,7 @@ class Twig_Extension_Core extends Twig_Extension
|
|||
* Cycles over a value.
|
||||
*
|
||||
* @param ArrayAccess|array $values An array or an ArrayAccess instance
|
||||
* @param integer $position The cycle position
|
||||
* @param int $position The cycle position
|
||||
*
|
||||
* @return string The next value in the cycle
|
||||
*/
|
||||
|
|
@ -374,10 +389,10 @@ function twig_cycle($values, $position)
|
|||
* Returns a random value depending on the supplied parameter type:
|
||||
* - a random item from a Traversable or array
|
||||
* - a random character from a string
|
||||
* - a random integer between 0 and the integer parameter
|
||||
* - a random integer between 0 and the integer parameter.
|
||||
*
|
||||
* @param Twig_Environment $env A Twig_Environment instance
|
||||
* @param Traversable|array|integer|string $values The values to pick a random item from
|
||||
* @param Twig_Environment $env A Twig_Environment instance
|
||||
* @param Traversable|array|int|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).
|
||||
*
|
||||
|
|
@ -436,10 +451,10 @@ function twig_random(Twig_Environment $env, $values = null)
|
|||
* {{ post.published_at|date("m/d/Y") }}
|
||||
* </pre>
|
||||
*
|
||||
* @param Twig_Environment $env A Twig_Environment instance
|
||||
* @param DateTime|DateInterval|string $date A date
|
||||
* @param string $format A format
|
||||
* @param DateTimeZone|string $timezone A timezone
|
||||
* @param Twig_Environment $env A Twig_Environment instance
|
||||
* @param DateTime|DateTimeInterface|DateInterval|string $date A date
|
||||
* @param string|null $format The target format, null to use the default
|
||||
* @param DateTimeZone|string|null|false $timezone The target timezone, null to use the default, false to leave unchanged
|
||||
*
|
||||
* @return string The formatted date
|
||||
*/
|
||||
|
|
@ -458,24 +473,27 @@ function twig_date_format_filter(Twig_Environment $env, $date, $format = null, $
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns a new date object modified
|
||||
* 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
|
||||
* @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);
|
||||
$resultDate = $date->modify($modifier);
|
||||
|
||||
return $date;
|
||||
// This is a hack to ensure PHP 5.2 support and support for DateTimeImmutable
|
||||
// DateTime::modify does not return the modified DateTime object < 5.3.0
|
||||
// and DateTimeImmutable does not modify $date.
|
||||
return null === $resultDate ? $date : $resultDate;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -487,58 +505,87 @@ function twig_date_modify_filter(Twig_Environment $env, $date, $modifier)
|
|||
* {% endif %}
|
||||
* </pre>
|
||||
*
|
||||
* @param Twig_Environment $env A Twig_Environment instance
|
||||
* @param DateTime|string $date A date
|
||||
* @param DateTimeZone|string $timezone A timezone
|
||||
* @param Twig_Environment $env A Twig_Environment instance
|
||||
* @param DateTime|DateTimeInterface|string|null $date A date
|
||||
* @param DateTimeZone|string|null|false $timezone The target timezone, null to use the default, false to leave unchanged
|
||||
*
|
||||
* @return DateTime A DateTime instance
|
||||
*/
|
||||
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 (false !== $timezone) {
|
||||
if (null === $timezone) {
|
||||
$timezone = $env->getExtension('core')->getTimezone();
|
||||
} elseif (!$timezone instanceof DateTimeZone) {
|
||||
$timezone = new DateTimeZone($timezone);
|
||||
}
|
||||
}
|
||||
|
||||
// immutable dates
|
||||
if ($date instanceof DateTimeImmutable) {
|
||||
return false !== $timezone ? $date->setTimezone($defaultTimezone) : $date;
|
||||
return false !== $timezone ? $date->setTimezone($timezone) : $date;
|
||||
}
|
||||
|
||||
if ($date instanceof DateTime || $date instanceof DateTimeInterface) {
|
||||
$date = clone $date;
|
||||
if (false !== $timezone) {
|
||||
$date->setTimezone($defaultTimezone);
|
||||
$date->setTimezone($timezone);
|
||||
}
|
||||
|
||||
return $date;
|
||||
}
|
||||
|
||||
$asString = (string) $date;
|
||||
if (ctype_digit($asString) || (!empty($asString) && '-' === $asString[0] && ctype_digit(substr($asString, 1)))) {
|
||||
$date = '@'.$date;
|
||||
if (null === $date || 'now' === $date) {
|
||||
return new DateTime($date, false !== $timezone ? $timezone : $env->getExtension('core')->getTimezone());
|
||||
}
|
||||
|
||||
$asString = (string) $date;
|
||||
if (ctype_digit($asString) || (!empty($asString) && '-' === $asString[0] && ctype_digit(substr($asString, 1)))) {
|
||||
$date = new DateTime('@'.$date);
|
||||
} else {
|
||||
$date = new DateTime($date, $env->getExtension('core')->getTimezone());
|
||||
}
|
||||
|
||||
$date = new DateTime($date, $defaultTimezone);
|
||||
if (false !== $timezone) {
|
||||
$date->setTimezone($defaultTimezone);
|
||||
$date->setTimezone($timezone);
|
||||
}
|
||||
|
||||
return $date;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces strings within a string.
|
||||
*
|
||||
* @param string $str String to replace in
|
||||
* @param array|Traversable $from Replace values
|
||||
* @param string|null $to Replace to, deprecated (@see http://php.net/manual/en/function.strtr.php)
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function twig_replace_filter($str, $from, $to = null)
|
||||
{
|
||||
if ($from instanceof Traversable) {
|
||||
$from = iterator_to_array($from);
|
||||
} elseif (is_string($from) && is_string($to)) {
|
||||
@trigger_error('Using "replace" with character by character replacement is deprecated and will be removed in Twig 2.0', E_USER_DEPRECATED);
|
||||
|
||||
return strtr($str, $from, $to);
|
||||
} elseif (!is_array($from)) {
|
||||
throw new Twig_Error_Runtime(sprintf('The "replace" filter expects an array or "Traversable" as replace values, got "%s".',is_object($from) ? get_class($from) : gettype($from)));
|
||||
}
|
||||
|
||||
return strtr($str, $from);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rounds a number.
|
||||
*
|
||||
* @param integer|float $value The value to round
|
||||
* @param integer|float $precision The rounding precision
|
||||
* @param string $method The method to use for rounding
|
||||
* @param int|float $value The value to round
|
||||
* @param int|float $precision The rounding precision
|
||||
* @param string $method The method to use for rounding
|
||||
*
|
||||
* @return integer|float The rounded number
|
||||
* @return int|float The rounded number
|
||||
*/
|
||||
function twig_round($value, $precision = 0, $method = 'common')
|
||||
{
|
||||
|
|
@ -560,11 +607,11 @@ function twig_round($value, $precision = 0, $method = 'common')
|
|||
* be used. Supplying any of the parameters will override the defaults set in the
|
||||
* environment object.
|
||||
*
|
||||
* @param Twig_Environment $env A Twig_Environment instance
|
||||
* @param mixed $number A float/int/string of the number to format
|
||||
* @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.
|
||||
* @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 string $decimalPoint The character(s) to use for the decimal point.
|
||||
* @param string $thousandSep The character(s) to use for the thousands separator.
|
||||
*
|
||||
* @return string The formatted number
|
||||
*/
|
||||
|
|
@ -587,32 +634,31 @@ function twig_number_format_filter(Twig_Environment $env, $number, $decimal = nu
|
|||
}
|
||||
|
||||
/**
|
||||
* URL encodes a string as a path segment or an array as a query string.
|
||||
* URL encodes (RFC 3986) a string as a path segment or an array as a query string.
|
||||
*
|
||||
* @param string|array $url A URL or an array of query parameters
|
||||
* @param Boolean $raw true to use rawurlencode() instead of urlencode
|
||||
*
|
||||
* @return string The URL encoded value
|
||||
*/
|
||||
function twig_urlencode_filter($url, $raw = false)
|
||||
function twig_urlencode_filter($url)
|
||||
{
|
||||
if (is_array($url)) {
|
||||
if (defined('PHP_QUERY_RFC3986')) {
|
||||
return http_build_query($url, '', '&', PHP_QUERY_RFC3986);
|
||||
}
|
||||
|
||||
return http_build_query($url, '', '&');
|
||||
}
|
||||
|
||||
if ($raw) {
|
||||
return rawurlencode($url);
|
||||
}
|
||||
|
||||
return urlencode($url);
|
||||
return rawurlencode($url);
|
||||
}
|
||||
|
||||
if (version_compare(PHP_VERSION, '5.3.0', '<')) {
|
||||
if (PHP_VERSION_ID < 50300) {
|
||||
/**
|
||||
* JSON encodes a variable.
|
||||
*
|
||||
* @param mixed $value The value to encode.
|
||||
* @param integer $options Not used on PHP 5.2.x
|
||||
* @param mixed $value The value to encode.
|
||||
* @param int $options Not used on PHP 5.2.x
|
||||
*
|
||||
* @return mixed The JSON encoded value
|
||||
*/
|
||||
|
|
@ -630,8 +676,8 @@ if (version_compare(PHP_VERSION, '5.3.0', '<')) {
|
|||
/**
|
||||
* JSON encodes a variable.
|
||||
*
|
||||
* @param mixed $value The value to encode.
|
||||
* @param integer $options Bitmask consisting of JSON_HEX_QUOT, JSON_HEX_TAG, JSON_HEX_AMP, JSON_HEX_APOS, JSON_NUMERIC_CHECK, JSON_PRETTY_PRINT, JSON_UNESCAPED_SLASHES, JSON_FORCE_OBJECT
|
||||
* @param mixed $value The value to encode.
|
||||
* @param int $options Bitmask consisting of JSON_HEX_QUOT, JSON_HEX_TAG, JSON_HEX_AMP, JSON_HEX_APOS, JSON_NUMERIC_CHECK, JSON_PRETTY_PRINT, JSON_UNESCAPED_SLASHES, JSON_FORCE_OBJECT
|
||||
*
|
||||
* @return mixed The JSON encoded value
|
||||
*/
|
||||
|
|
@ -665,15 +711,23 @@ function _twig_markup2string(&$value)
|
|||
* {# items now contains { 'apple': 'fruit', 'orange': 'fruit', 'peugeot': 'car' } #}
|
||||
* </pre>
|
||||
*
|
||||
* @param array $arr1 An array
|
||||
* @param array $arr2 An array
|
||||
* @param array|Traversable $arr1 An array
|
||||
* @param array|Traversable $arr2 An array
|
||||
*
|
||||
* @return array The merged array
|
||||
*/
|
||||
function twig_array_merge($arr1, $arr2)
|
||||
{
|
||||
if (!is_array($arr1) || !is_array($arr2)) {
|
||||
throw new Twig_Error_Runtime('The merge filter only works with arrays or hashes.');
|
||||
if ($arr1 instanceof Traversable) {
|
||||
$arr1 = iterator_to_array($arr1);
|
||||
} elseif (!is_array($arr1)) {
|
||||
throw new Twig_Error_Runtime(sprintf('The merge filter only works with arrays or "Traversable", got "%s" as first argument.', gettype($arr1)));
|
||||
}
|
||||
|
||||
if ($arr2 instanceof Traversable) {
|
||||
$arr2 = iterator_to_array($arr2);
|
||||
} elseif (!is_array($arr2)) {
|
||||
throw new Twig_Error_Runtime(sprintf('The merge filter only works with arrays or "Traversable", got "%s" as second argument.', gettype($arr2)));
|
||||
}
|
||||
|
||||
return array_merge($arr1, $arr2);
|
||||
|
|
@ -684,16 +738,28 @@ function twig_array_merge($arr1, $arr2)
|
|||
*
|
||||
* @param Twig_Environment $env A Twig_Environment instance
|
||||
* @param mixed $item A variable
|
||||
* @param integer $start Start of the slice
|
||||
* @param integer $length Size of the slice
|
||||
* @param Boolean $preserveKeys Whether to preserve key or not (when the input is an array)
|
||||
* @param int $start Start of the slice
|
||||
* @param int $length Size of the slice
|
||||
* @param bool $preserveKeys Whether to preserve key or not (when the input is an array)
|
||||
*
|
||||
* @return mixed The sliced variable
|
||||
*/
|
||||
function twig_slice(Twig_Environment $env, $item, $start, $length = null, $preserveKeys = false)
|
||||
{
|
||||
if ($item instanceof Traversable) {
|
||||
$item = iterator_to_array($item, false);
|
||||
if ($item instanceof IteratorAggregate) {
|
||||
$item = $item->getIterator();
|
||||
}
|
||||
|
||||
if ($start >= 0 && $length >= 0 && $item instanceof Iterator) {
|
||||
try {
|
||||
return iterator_to_array(new LimitIterator($item, $start, $length === null ? -1 : $length), $preserveKeys);
|
||||
} catch (OutOfBoundsException $exception) {
|
||||
return array();
|
||||
}
|
||||
}
|
||||
|
||||
$item = iterator_to_array($item, $preserveKeys);
|
||||
}
|
||||
|
||||
if (is_array($item)) {
|
||||
|
|
@ -703,10 +769,10 @@ function twig_slice(Twig_Environment $env, $item, $start, $length = null, $prese
|
|||
$item = (string) $item;
|
||||
|
||||
if (function_exists('mb_get_info') && null !== $charset = $env->getCharset()) {
|
||||
return mb_substr($item, $start, null === $length ? mb_strlen($item, $charset) - $start : $length, $charset);
|
||||
return (string) mb_substr($item, $start, null === $length ? mb_strlen($item, $charset) - $start : $length, $charset);
|
||||
}
|
||||
|
||||
return null === $length ? substr($item, $start) : substr($item, $start, $length);
|
||||
return (string) (null === $length ? substr($item, $start) : substr($item, $start, $length));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -783,24 +849,45 @@ function twig_join_filter($value, $glue = '')
|
|||
* {# returns [aa, bb, cc] #}
|
||||
* </pre>
|
||||
*
|
||||
* @param string $value A string
|
||||
* @param string $delimiter The delimiter
|
||||
* @param integer $limit The limit
|
||||
* @param string $value A string
|
||||
* @param string $delimiter The delimiter
|
||||
* @param int $limit The limit
|
||||
*
|
||||
* @return array The split string as an array
|
||||
*/
|
||||
function twig_split_filter($value, $delimiter, $limit = null)
|
||||
function twig_split_filter(Twig_Environment $env, $value, $delimiter, $limit = null)
|
||||
{
|
||||
if (empty($delimiter)) {
|
||||
if (!empty($delimiter)) {
|
||||
return null === $limit ? explode($delimiter, $value) : explode($delimiter, $value, $limit);
|
||||
}
|
||||
|
||||
if (!function_exists('mb_get_info') || null === $charset = $env->getCharset()) {
|
||||
return str_split($value, null === $limit ? 1 : $limit);
|
||||
}
|
||||
|
||||
return null === $limit ? explode($delimiter, $value) : explode($delimiter, $value, $limit);
|
||||
if ($limit <= 1) {
|
||||
return preg_split('/(?<!^)(?!$)/u', $value);
|
||||
}
|
||||
|
||||
$length = mb_strlen($value, $charset);
|
||||
if ($length < $limit) {
|
||||
return array($value);
|
||||
}
|
||||
|
||||
$r = array();
|
||||
for ($i = 0; $i < $length; $i += $limit) {
|
||||
$r[] = mb_substr($value, $i, $limit, $charset);
|
||||
}
|
||||
|
||||
return $r;
|
||||
}
|
||||
|
||||
// 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.
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
function _twig_default_filter($value, $default = '')
|
||||
{
|
||||
if (twig_test_empty($value)) {
|
||||
|
|
@ -827,7 +914,7 @@ function _twig_default_filter($value, $default = '')
|
|||
*/
|
||||
function twig_get_array_keys_filter($array)
|
||||
{
|
||||
if (is_object($array) && $array instanceof Traversable) {
|
||||
if ($array instanceof Traversable) {
|
||||
return array_keys(iterator_to_array($array));
|
||||
}
|
||||
|
||||
|
|
@ -843,13 +930,13 @@ function twig_get_array_keys_filter($array)
|
|||
*
|
||||
* @param Twig_Environment $env A Twig_Environment instance
|
||||
* @param array|Traversable|string $item An array, a Traversable instance, or a string
|
||||
* @param Boolean $preserveKeys Whether to preserve key or not
|
||||
* @param bool $preserveKeys Whether to preserve key or not
|
||||
*
|
||||
* @return mixed The reversed input
|
||||
*/
|
||||
function twig_reverse_filter(Twig_Environment $env, $item, $preserveKeys = false)
|
||||
{
|
||||
if (is_object($item) && $item instanceof Traversable) {
|
||||
if ($item instanceof Traversable) {
|
||||
return array_reverse(iterator_to_array($item), $preserveKeys);
|
||||
}
|
||||
|
||||
|
|
@ -881,28 +968,34 @@ function twig_reverse_filter(Twig_Environment $env, $item, $preserveKeys = false
|
|||
/**
|
||||
* Sorts an array.
|
||||
*
|
||||
* @param array $array An array
|
||||
* @param array|Traversable $array
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function twig_sort_filter($array)
|
||||
{
|
||||
if ($array instanceof Traversable) {
|
||||
$array = iterator_to_array($array);
|
||||
} elseif (!is_array($array)) {
|
||||
throw new Twig_Error_Runtime(sprintf('The sort filter only works with arrays or "Traversable", got "%s".', gettype($array)));
|
||||
}
|
||||
|
||||
asort($array);
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
/* used internally */
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
function twig_in_filter($value, $compare)
|
||||
{
|
||||
if (is_array($compare)) {
|
||||
return in_array($value, $compare, is_object($value));
|
||||
} elseif (is_string($compare)) {
|
||||
if (!strlen($value)) {
|
||||
return empty($compare);
|
||||
}
|
||||
|
||||
return false !== strpos($compare, (string) $value);
|
||||
return in_array($value, $compare, is_object($value) || is_resource($value));
|
||||
} elseif (is_string($compare) && (is_string($value) || is_int($value) || is_float($value))) {
|
||||
return '' === $value || false !== strpos($compare, (string) $value);
|
||||
} elseif ($compare instanceof Traversable) {
|
||||
return in_array($value, iterator_to_array($compare, false), is_object($value));
|
||||
return in_array($value, iterator_to_array($compare, false), is_object($value) || is_resource($value));
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
@ -915,7 +1008,9 @@ function twig_in_filter($value, $compare)
|
|||
* @param string $string The value to be escaped
|
||||
* @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)
|
||||
* @param bool $autoescape Whether the function is called by the auto-escaping feature (true) or by the developer (false)
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function twig_escape_filter(Twig_Environment $env, $string, $strategy = 'html', $charset = null, $autoescape = false)
|
||||
{
|
||||
|
|
@ -926,7 +1021,7 @@ function twig_escape_filter(Twig_Environment $env, $string, $strategy = 'html',
|
|||
if (!is_string($string)) {
|
||||
if (is_object($string) && method_exists($string, '__toString')) {
|
||||
$string = (string) $string;
|
||||
} else {
|
||||
} elseif (in_array($strategy, array('html', 'js', 'css', 'html_attr', 'url'))) {
|
||||
return $string;
|
||||
}
|
||||
}
|
||||
|
|
@ -945,7 +1040,7 @@ function twig_escape_filter(Twig_Environment $env, $string, $strategy = 'html',
|
|||
static $htmlspecialcharsCharsets;
|
||||
|
||||
if (null === $htmlspecialcharsCharsets) {
|
||||
if ('hiphop' === substr(PHP_VERSION, -6)) {
|
||||
if (defined('HHVM_VERSION')) {
|
||||
$htmlspecialcharsCharsets = array('utf-8' => true, 'UTF-8' => true);
|
||||
} else {
|
||||
$htmlspecialcharsCharsets = array(
|
||||
|
|
@ -1037,9 +1132,7 @@ function twig_escape_filter(Twig_Environment $env, $string, $strategy = 'html',
|
|||
return $string;
|
||||
|
||||
case 'url':
|
||||
// hackish test to avoid version_compare that is much slower, this works unless PHP releases a 5.10.*
|
||||
// at that point however PHP 5.2.* support can be removed
|
||||
if (PHP_VERSION < '5.3.0') {
|
||||
if (PHP_VERSION_ID < 50300) {
|
||||
return str_replace('%7E', '~', rawurlencode($string));
|
||||
}
|
||||
|
||||
|
|
@ -1062,7 +1155,9 @@ function twig_escape_filter(Twig_Environment $env, $string, $strategy = 'html',
|
|||
}
|
||||
}
|
||||
|
||||
/* used internally */
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
function twig_escape_filter_is_safe(Twig_Node $filterArgs)
|
||||
{
|
||||
foreach ($filterArgs as $arg) {
|
||||
|
|
@ -1152,7 +1247,7 @@ function _twig_escape_html_attr_callback($matches)
|
|||
$chr = $matches[0];
|
||||
$ord = ord($chr);
|
||||
|
||||
/**
|
||||
/*
|
||||
* The following replaces characters undefined in HTML with the
|
||||
* hex entity for the Unicode replacement character.
|
||||
*/
|
||||
|
|
@ -1160,7 +1255,7 @@ function _twig_escape_html_attr_callback($matches)
|
|||
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.
|
||||
*/
|
||||
|
|
@ -1176,11 +1271,10 @@ function _twig_escape_html_attr_callback($matches)
|
|||
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);
|
||||
}
|
||||
|
||||
|
|
@ -1192,7 +1286,7 @@ if (function_exists('mb_get_info')) {
|
|||
* @param Twig_Environment $env A Twig_Environment instance
|
||||
* @param mixed $thing A variable
|
||||
*
|
||||
* @return integer The length of the value
|
||||
* @return int The length of the value
|
||||
*/
|
||||
function twig_length_filter(Twig_Environment $env, $thing)
|
||||
{
|
||||
|
|
@ -1260,9 +1354,8 @@ if (function_exists('mb_get_info')) {
|
|||
*/
|
||||
function twig_capitalize_string_filter(Twig_Environment $env, $string)
|
||||
{
|
||||
if (null !== ($charset = $env->getCharset())) {
|
||||
return mb_strtoupper(mb_substr($string, 0, 1, $charset), $charset).
|
||||
mb_strtolower(mb_substr($string, 1, mb_strlen($string, $charset), $charset), $charset);
|
||||
if (null !== $charset = $env->getCharset()) {
|
||||
return mb_strtoupper(mb_substr($string, 0, 1, $charset), $charset).mb_strtolower(mb_substr($string, 1, mb_strlen($string, $charset), $charset), $charset);
|
||||
}
|
||||
|
||||
return ucfirst(strtolower($string));
|
||||
|
|
@ -1276,7 +1369,7 @@ else {
|
|||
* @param Twig_Environment $env A Twig_Environment instance
|
||||
* @param mixed $thing A variable
|
||||
*
|
||||
* @return integer The length of the value
|
||||
* @return int The length of the value
|
||||
*/
|
||||
function twig_length_filter(Twig_Environment $env, $thing)
|
||||
{
|
||||
|
|
@ -1310,7 +1403,9 @@ else {
|
|||
}
|
||||
}
|
||||
|
||||
/* used internally */
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
function twig_ensure_traversable($seq)
|
||||
{
|
||||
if ($seq instanceof Traversable || is_array($seq)) {
|
||||
|
|
@ -1332,7 +1427,7 @@ function twig_ensure_traversable($seq)
|
|||
*
|
||||
* @param mixed $value A variable
|
||||
*
|
||||
* @return Boolean true if the value is empty, false otherwise
|
||||
* @return bool true if the value is empty, false otherwise
|
||||
*/
|
||||
function twig_test_empty($value)
|
||||
{
|
||||
|
|
@ -1355,7 +1450,7 @@ function twig_test_empty($value)
|
|||
*
|
||||
* @param mixed $value A variable
|
||||
*
|
||||
* @return Boolean true if the value is traversable
|
||||
* @return bool true if the value is traversable
|
||||
*/
|
||||
function twig_test_iterable($value)
|
||||
{
|
||||
|
|
@ -1365,11 +1460,13 @@ function twig_test_iterable($value)
|
|||
/**
|
||||
* Renders a template.
|
||||
*
|
||||
* @param string|array $template The template to render or an array of templates to try consecutively
|
||||
* @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
|
||||
* @param Twig_Environment $env
|
||||
* @param array $context
|
||||
* @param string|array $template The template to render or an array of templates to try consecutively
|
||||
* @param array $variables The variables to pass to the template
|
||||
* @param bool $withContext
|
||||
* @param bool $ignoreMissing Whether to ignore missing templates or not
|
||||
* @param bool $sandboxed Whether to sandbox the template or not
|
||||
*
|
||||
* @return string The rendered template
|
||||
*/
|
||||
|
|
@ -1388,10 +1485,15 @@ function twig_include(Twig_Environment $env, $context, $template, $variables = a
|
|||
}
|
||||
}
|
||||
|
||||
$result = null;
|
||||
try {
|
||||
return $env->resolveTemplate($template)->render($variables);
|
||||
$result = $env->resolveTemplate($template)->render($variables);
|
||||
} catch (Twig_Error_Loader $e) {
|
||||
if (!$ignoreMissing) {
|
||||
if ($isSandboxed && !$alreadySandboxed) {
|
||||
$sandbox->disableSandbox();
|
||||
}
|
||||
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
|
@ -1399,18 +1501,27 @@ function twig_include(Twig_Environment $env, $context, $template, $variables = a
|
|||
if ($isSandboxed && !$alreadySandboxed) {
|
||||
$sandbox->disableSandbox();
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a template content without rendering it.
|
||||
*
|
||||
* @param string $name The template name
|
||||
* @param string $name The template name
|
||||
* @param bool $ignoreMissing Whether to ignore missing templates or not
|
||||
*
|
||||
* @return string The template source
|
||||
*/
|
||||
function twig_source(Twig_Environment $env, $name)
|
||||
function twig_source(Twig_Environment $env, $name, $ignoreMissing = false)
|
||||
{
|
||||
return $env->getLoader()->getSource($name);
|
||||
try {
|
||||
return $env->getLoader()->getSource($name);
|
||||
} catch (Twig_Error_Loader $e) {
|
||||
if (!$ignoreMissing) {
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1433,9 +1544,9 @@ function twig_constant($constant, $object = null)
|
|||
/**
|
||||
* Batches item.
|
||||
*
|
||||
* @param array $items An array of items
|
||||
* @param integer $size The size of the batch
|
||||
* @param mixed $fill A value used to fill missing items
|
||||
* @param array $items An array of items
|
||||
* @param int $size The size of the batch
|
||||
* @param mixed $fill A value used to fill missing items
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
|
|
@ -1449,7 +1560,7 @@ function twig_array_batch($items, $size, $fill = null)
|
|||
|
||||
$result = array_chunk($items, $size, true);
|
||||
|
||||
if (null !== $fill) {
|
||||
if (null !== $fill && !empty($result)) {
|
||||
$last = count($result) - 1;
|
||||
if ($fillCount = $size - count($result[$last])) {
|
||||
$result[$last] = array_merge(
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ function twig_var_dump(Twig_Environment $env, $context)
|
|||
|
||||
var_dump($vars);
|
||||
} else {
|
||||
for ($i = 2; $i < $count; $i++) {
|
||||
for ($i = 2; $i < $count; ++$i) {
|
||||
var_dump(func_get_arg($i));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,13 @@ class Twig_Extension_Escaper extends Twig_Extension
|
|||
{
|
||||
protected $defaultStrategy;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string|false|callable $defaultStrategy An escaping strategy
|
||||
*
|
||||
* @see setDefaultStrategy()
|
||||
*/
|
||||
public function __construct($defaultStrategy = 'html')
|
||||
{
|
||||
$this->setDefaultStrategy($defaultStrategy);
|
||||
|
|
@ -55,15 +62,21 @@ class Twig_Extension_Escaper extends Twig_Extension
|
|||
* 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
|
||||
* @param string|false|callable $defaultStrategy An escaping strategy
|
||||
*/
|
||||
public function setDefaultStrategy($defaultStrategy)
|
||||
{
|
||||
// for BC
|
||||
if (true === $defaultStrategy) {
|
||||
@trigger_error('Using "true" as the default strategy is deprecated. Use "html" instead.', E_USER_DEPRECATED);
|
||||
|
||||
$defaultStrategy = 'html';
|
||||
}
|
||||
|
||||
if ('filename' === $defaultStrategy) {
|
||||
$defaultStrategy = array('Twig_FileExtensionEscapingStrategy', 'guess');
|
||||
}
|
||||
|
||||
$this->defaultStrategy = $defaultStrategy;
|
||||
}
|
||||
|
||||
|
|
@ -72,13 +85,13 @@ class Twig_Extension_Escaper extends Twig_Extension
|
|||
*
|
||||
* @param string $filename The template "filename"
|
||||
*
|
||||
* @return string The default strategy to use for the template
|
||||
* @return string|false The default strategy to use for the template
|
||||
*/
|
||||
public function getDefaultStrategy($filename)
|
||||
{
|
||||
// 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)) {
|
||||
if (!is_string($this->defaultStrategy) && false !== $this->defaultStrategy) {
|
||||
return call_user_func($this->defaultStrategy, $filename);
|
||||
}
|
||||
|
||||
|
|
@ -100,6 +113,8 @@ class Twig_Extension_Escaper extends Twig_Extension
|
|||
* Marks a variable as being safe.
|
||||
*
|
||||
* @param string $string A PHP variable
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function twig_raw_filter($string)
|
||||
{
|
||||
|
|
|
|||
52
www/analytics/vendor/twig/twig/lib/Twig/Extension/Profiler.php
vendored
Normal file
52
www/analytics/vendor/twig/twig/lib/Twig/Extension/Profiler.php
vendored
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2015 Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
class Twig_Extension_Profiler extends Twig_Extension
|
||||
{
|
||||
private $actives = array();
|
||||
|
||||
public function __construct(Twig_Profiler_Profile $profile)
|
||||
{
|
||||
$this->actives[] = $profile;
|
||||
}
|
||||
|
||||
public function enter(Twig_Profiler_Profile $profile)
|
||||
{
|
||||
$this->actives[0]->addProfile($profile);
|
||||
array_unshift($this->actives, $profile);
|
||||
}
|
||||
|
||||
public function leave(Twig_Profiler_Profile $profile)
|
||||
{
|
||||
$profile->leave();
|
||||
array_shift($this->actives);
|
||||
|
||||
if (1 === count($this->actives)) {
|
||||
$this->actives[0]->leave();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getNodeVisitors()
|
||||
{
|
||||
return array(new Twig_Profiler_NodeVisitor_Profiler($this->getName()));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'profiler';
|
||||
}
|
||||
}
|
||||
|
|
@ -16,7 +16,7 @@ class Twig_Extension_Sandbox extends Twig_Extension
|
|||
|
||||
public function __construct(Twig_Sandbox_SecurityPolicyInterface $policy, $sandboxed = false)
|
||||
{
|
||||
$this->policy = $policy;
|
||||
$this->policy = $policy;
|
||||
$this->sandboxedGlobally = $sandboxed;
|
||||
}
|
||||
|
||||
|
|
@ -93,7 +93,7 @@ class Twig_Extension_Sandbox extends Twig_Extension
|
|||
|
||||
public function ensureToStringAllowed($obj)
|
||||
{
|
||||
if (is_object($obj)) {
|
||||
if ($this->isSandboxed() && is_object($obj)) {
|
||||
$this->policy->checkMethodAllowed($obj, '__toString');
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@
|
|||
* This class is used by Twig_Environment as a staging area and must not be used directly.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class Twig_Extension_Staging extends Twig_Extension
|
||||
{
|
||||
|
|
|
|||
|
|
@ -37,28 +37,11 @@ class Twig_Extension_StringLoader extends Twig_Extension
|
|||
* </pre>
|
||||
*
|
||||
* @param Twig_Environment $env A Twig_Environment instance
|
||||
* @param string $template A template as a string
|
||||
* @param string $template A template as a string or object implementing __toString()
|
||||
*
|
||||
* @return Twig_Template A Twig_Template instance
|
||||
*/
|
||||
function twig_template_from_string(Twig_Environment $env, $template)
|
||||
{
|
||||
$name = sprintf('__string_template__%s', hash('sha256', uniqid(mt_rand(), true), false));
|
||||
|
||||
$loader = new Twig_Loader_Chain(array(
|
||||
new Twig_Loader_Array(array($name => $template)),
|
||||
$current = $env->getLoader(),
|
||||
));
|
||||
|
||||
$env->setLoader($loader);
|
||||
try {
|
||||
$template = $env->loadTemplate($name);
|
||||
} catch (Exception $e) {
|
||||
$env->setLoader($current);
|
||||
|
||||
throw $e;
|
||||
}
|
||||
$env->setLoader($current);
|
||||
|
||||
return $template;
|
||||
return $env->createTemplate((string) $template);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ interface Twig_ExtensionInterface
|
|||
/**
|
||||
* Returns the token parser instances to add to the existing list.
|
||||
*
|
||||
* @return array An array of Twig_TokenParserInterface or Twig_TokenParserBrokerInterface instances
|
||||
* @return Twig_TokenParserInterface[]
|
||||
*/
|
||||
public function getTokenParsers();
|
||||
|
||||
|
|
@ -42,21 +42,21 @@ interface Twig_ExtensionInterface
|
|||
/**
|
||||
* Returns a list of filters to add to the existing list.
|
||||
*
|
||||
* @return array An array of filters
|
||||
* @return Twig_SimpleFilter[]
|
||||
*/
|
||||
public function getFilters();
|
||||
|
||||
/**
|
||||
* Returns a list of tests to add to the existing list.
|
||||
*
|
||||
* @return array An array of tests
|
||||
* @return Twig_SimpleTest[]
|
||||
*/
|
||||
public function getTests();
|
||||
|
||||
/**
|
||||
* Returns a list of functions to add to the existing list.
|
||||
*
|
||||
* @return array An array of functions
|
||||
* @return Twig_SimpleFunction[]
|
||||
*/
|
||||
public function getFunctions();
|
||||
|
||||
|
|
|
|||
58
www/analytics/vendor/twig/twig/lib/Twig/FileExtensionEscapingStrategy.php
vendored
Normal file
58
www/analytics/vendor/twig/twig/lib/Twig/FileExtensionEscapingStrategy.php
vendored
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2015 Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Default autoescaping strategy based on file names.
|
||||
*
|
||||
* This strategy sets the HTML as the default autoescaping strategy,
|
||||
* but changes it based on the filename.
|
||||
*
|
||||
* Note that there is no runtime performance impact as the
|
||||
* default autoescaping strategy is set at compilation time.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class Twig_FileExtensionEscapingStrategy
|
||||
{
|
||||
/**
|
||||
* Guesses the best autoescaping strategy based on the file name.
|
||||
*
|
||||
* @param string $filename The template file name
|
||||
*
|
||||
* @return string|false The escaping strategy name to use or false to disable
|
||||
*/
|
||||
public static function guess($filename)
|
||||
{
|
||||
if (in_array(substr($filename, -1), array('/', '\\'))) {
|
||||
return 'html'; // return html for directories
|
||||
}
|
||||
|
||||
if ('.twig' === substr($filename, -5)) {
|
||||
$filename = substr($filename, 0, -5);
|
||||
}
|
||||
|
||||
$extension = pathinfo($filename, PATHINFO_EXTENSION);
|
||||
|
||||
switch ($extension) {
|
||||
case 'js':
|
||||
return 'js';
|
||||
|
||||
case 'css':
|
||||
return 'css';
|
||||
|
||||
case 'txt':
|
||||
return false;
|
||||
|
||||
default:
|
||||
return 'html';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -9,12 +9,15 @@
|
|||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
@trigger_error('The Twig_Filter class is deprecated since version 1.12 and will be removed in 2.0. Use Twig_SimpleFilter instead.', E_USER_DEPRECATED);
|
||||
|
||||
/**
|
||||
* Represents a template filter.
|
||||
*
|
||||
* Use Twig_SimpleFilter instead.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @deprecated since 1.12 (to be removed in 2.0)
|
||||
*/
|
||||
abstract class Twig_Filter implements Twig_FilterInterface, Twig_FilterCallableInterface
|
||||
|
|
@ -26,10 +29,10 @@ abstract class Twig_Filter implements Twig_FilterInterface, Twig_FilterCallableI
|
|||
{
|
||||
$this->options = array_merge(array(
|
||||
'needs_environment' => false,
|
||||
'needs_context' => false,
|
||||
'pre_escape' => null,
|
||||
'preserves_safety' => null,
|
||||
'callable' => null,
|
||||
'needs_context' => false,
|
||||
'pre_escape' => null,
|
||||
'preserves_safety' => null,
|
||||
'callable' => null,
|
||||
), $options);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,12 +9,15 @@
|
|||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
@trigger_error('The Twig_Filter_Function class is deprecated since version 1.12 and will be removed in 2.0. Use Twig_SimpleFilter instead.', E_USER_DEPRECATED);
|
||||
|
||||
/**
|
||||
* Represents a function template filter.
|
||||
*
|
||||
* Use Twig_SimpleFilter instead.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @deprecated since 1.12 (to be removed in 2.0)
|
||||
*/
|
||||
class Twig_Filter_Function extends Twig_Filter
|
||||
|
|
|
|||
|
|
@ -9,12 +9,15 @@
|
|||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
@trigger_error('The Twig_Filter_Method class is deprecated since version 1.12 and will be removed in 2.0. Use Twig_SimpleFilter instead.', E_USER_DEPRECATED);
|
||||
|
||||
/**
|
||||
* Represents a method template filter.
|
||||
*
|
||||
* Use Twig_SimpleFilter instead.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @deprecated since 1.12 (to be removed in 2.0)
|
||||
*/
|
||||
class Twig_Filter_Method extends Twig_Filter
|
||||
|
|
|
|||
|
|
@ -9,12 +9,15 @@
|
|||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
@trigger_error('The Twig_Filter_Node class is deprecated since version 1.12 and will be removed in 2.0. Use Twig_SimpleFilter instead.', E_USER_DEPRECATED);
|
||||
|
||||
/**
|
||||
* Represents a template filter as a node.
|
||||
*
|
||||
* Use Twig_SimpleFilter instead.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @deprecated since 1.12 (to be removed in 2.0)
|
||||
*/
|
||||
class Twig_Filter_Node extends Twig_Filter
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
* Use Twig_SimpleFilter instead.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @deprecated since 1.12 (to be removed in 2.0)
|
||||
*/
|
||||
interface Twig_FilterCallableInterface
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
* Use Twig_SimpleFilter instead.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @deprecated since 1.12 (to be removed in 2.0)
|
||||
*/
|
||||
interface Twig_FilterInterface
|
||||
|
|
|
|||
|
|
@ -9,12 +9,15 @@
|
|||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
@trigger_error('The Twig_Function class is deprecated since version 1.12 and will be removed in 2.0. Use Twig_SimpleFunction instead.', E_USER_DEPRECATED);
|
||||
|
||||
/**
|
||||
* Represents a template function.
|
||||
*
|
||||
* Use Twig_SimpleFunction instead.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @deprecated since 1.12 (to be removed in 2.0)
|
||||
*/
|
||||
abstract class Twig_Function implements Twig_FunctionInterface, Twig_FunctionCallableInterface
|
||||
|
|
@ -26,8 +29,8 @@ abstract class Twig_Function implements Twig_FunctionInterface, Twig_FunctionCal
|
|||
{
|
||||
$this->options = array_merge(array(
|
||||
'needs_environment' => false,
|
||||
'needs_context' => false,
|
||||
'callable' => null,
|
||||
'needs_context' => false,
|
||||
'callable' => null,
|
||||
), $options);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,12 +10,15 @@
|
|||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
@trigger_error('The Twig_Function_Function class is deprecated since version 1.12 and will be removed in 2.0. Use Twig_SimpleFunction instead.', E_USER_DEPRECATED);
|
||||
|
||||
/**
|
||||
* Represents a function template function.
|
||||
*
|
||||
* Use Twig_SimpleFunction instead.
|
||||
*
|
||||
* @author Arnaud Le Blanc <arnaud.lb@gmail.com>
|
||||
*
|
||||
* @deprecated since 1.12 (to be removed in 2.0)
|
||||
*/
|
||||
class Twig_Function_Function extends Twig_Function
|
||||
|
|
|
|||
|
|
@ -10,12 +10,15 @@
|
|||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
@trigger_error('The Twig_Function_Method class is deprecated since version 1.12 and will be removed in 2.0. Use Twig_SimpleFunction instead.', E_USER_DEPRECATED);
|
||||
|
||||
/**
|
||||
* Represents a method template function.
|
||||
*
|
||||
* Use Twig_SimpleFunction instead.
|
||||
*
|
||||
* @author Arnaud Le Blanc <arnaud.lb@gmail.com>
|
||||
*
|
||||
* @deprecated since 1.12 (to be removed in 2.0)
|
||||
*/
|
||||
class Twig_Function_Method extends Twig_Function
|
||||
|
|
|
|||
|
|
@ -9,12 +9,15 @@
|
|||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
@trigger_error('The Twig_Function_Node class is deprecated since version 1.12 and will be removed in 2.0. Use Twig_SimpleFunction instead.', E_USER_DEPRECATED);
|
||||
|
||||
/**
|
||||
* Represents a template function as a node.
|
||||
*
|
||||
* Use Twig_SimpleFunction instead.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @deprecated since 1.12 (to be removed in 2.0)
|
||||
*/
|
||||
class Twig_Function_Node extends Twig_Function
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
* Use Twig_SimpleFunction instead.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @deprecated since 1.12 (to be removed in 2.0)
|
||||
*/
|
||||
interface Twig_FunctionCallableInterface
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
* Use Twig_SimpleFunction instead.
|
||||
*
|
||||
* @author Arnaud Le Blanc <arnaud.lb@gmail.com>
|
||||
*
|
||||
* @deprecated since 1.12 (to be removed in 2.0)
|
||||
*/
|
||||
interface Twig_FunctionInterface
|
||||
|
|
|
|||
|
|
@ -33,42 +33,42 @@ class Twig_Lexer implements Twig_LexerInterface
|
|||
protected $positions;
|
||||
protected $currentVarBlockLine;
|
||||
|
||||
const STATE_DATA = 0;
|
||||
const STATE_BLOCK = 1;
|
||||
const STATE_VAR = 2;
|
||||
const STATE_STRING = 3;
|
||||
const STATE_INTERPOLATION = 4;
|
||||
const STATE_DATA = 0;
|
||||
const STATE_BLOCK = 1;
|
||||
const STATE_VAR = 2;
|
||||
const STATE_STRING = 3;
|
||||
const STATE_INTERPOLATION = 4;
|
||||
|
||||
const REGEX_NAME = '/[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/A';
|
||||
const REGEX_NUMBER = '/[0-9]+(?:\.[0-9]+)?/A';
|
||||
const REGEX_STRING = '/"([^#"\\\\]*(?:\\\\.[^#"\\\\]*)*)"|\'([^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\'/As';
|
||||
const REGEX_NAME = '/[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/A';
|
||||
const REGEX_NUMBER = '/[0-9]+(?:\.[0-9]+)?/A';
|
||||
const REGEX_STRING = '/"([^#"\\\\]*(?:\\\\.[^#"\\\\]*)*)"|\'([^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\'/As';
|
||||
const REGEX_DQ_STRING_DELIM = '/"/A';
|
||||
const REGEX_DQ_STRING_PART = '/[^#"\\\\]*(?:(?:\\\\.|#(?!\{))[^#"\\\\]*)*/As';
|
||||
const PUNCTUATION = '()[]{}?:.,|';
|
||||
const REGEX_DQ_STRING_PART = '/[^#"\\\\]*(?:(?:\\\\.|#(?!\{))[^#"\\\\]*)*/As';
|
||||
const PUNCTUATION = '()[]{}?:.,|';
|
||||
|
||||
public function __construct(Twig_Environment $env, array $options = array())
|
||||
{
|
||||
$this->env = $env;
|
||||
|
||||
$this->options = array_merge(array(
|
||||
'tag_comment' => array('{#', '#}'),
|
||||
'tag_block' => array('{%', '%}'),
|
||||
'tag_variable' => array('{{', '}}'),
|
||||
'tag_comment' => array('{#', '#}'),
|
||||
'tag_block' => array('{%', '%}'),
|
||||
'tag_variable' => array('{{', '}}'),
|
||||
'whitespace_trim' => '-',
|
||||
'interpolation' => array('#{', '}'),
|
||||
'interpolation' => array('#{', '}'),
|
||||
), $options);
|
||||
|
||||
$this->regexes = array(
|
||||
'lex_var' => '/\s*'.preg_quote($this->options['whitespace_trim'].$this->options['tag_variable'][1], '/').'\s*|\s*'.preg_quote($this->options['tag_variable'][1], '/').'/A',
|
||||
'lex_block' => '/\s*(?:'.preg_quote($this->options['whitespace_trim'].$this->options['tag_block'][1], '/').'\s*|\s*'.preg_quote($this->options['tag_block'][1], '/').')\n?/A',
|
||||
'lex_raw_data' => '/('.preg_quote($this->options['tag_block'][0].$this->options['whitespace_trim'], '/').'|'.preg_quote($this->options['tag_block'][0], '/').')\s*(?:end%s)\s*(?:'.preg_quote($this->options['whitespace_trim'].$this->options['tag_block'][1], '/').'\s*|\s*'.preg_quote($this->options['tag_block'][1], '/').')/s',
|
||||
'operator' => $this->getOperatorRegex(),
|
||||
'lex_comment' => '/(?:'.preg_quote($this->options['whitespace_trim'], '/').preg_quote($this->options['tag_comment'][1], '/').'\s*|'.preg_quote($this->options['tag_comment'][1], '/').')\n?/s',
|
||||
'lex_block_raw' => '/\s*(raw|verbatim)\s*(?:'.preg_quote($this->options['whitespace_trim'].$this->options['tag_block'][1], '/').'\s*|\s*'.preg_quote($this->options['tag_block'][1], '/').')/As',
|
||||
'lex_block_line' => '/\s*line\s+(\d+)\s*'.preg_quote($this->options['tag_block'][1], '/').'/As',
|
||||
'lex_tokens_start' => '/('.preg_quote($this->options['tag_variable'][0], '/').'|'.preg_quote($this->options['tag_block'][0], '/').'|'.preg_quote($this->options['tag_comment'][0], '/').')('.preg_quote($this->options['whitespace_trim'], '/').')?/s',
|
||||
'lex_var' => '/\s*'.preg_quote($this->options['whitespace_trim'].$this->options['tag_variable'][1], '/').'\s*|\s*'.preg_quote($this->options['tag_variable'][1], '/').'/A',
|
||||
'lex_block' => '/\s*(?:'.preg_quote($this->options['whitespace_trim'].$this->options['tag_block'][1], '/').'\s*|\s*'.preg_quote($this->options['tag_block'][1], '/').')\n?/A',
|
||||
'lex_raw_data' => '/('.preg_quote($this->options['tag_block'][0].$this->options['whitespace_trim'], '/').'|'.preg_quote($this->options['tag_block'][0], '/').')\s*(?:end%s)\s*(?:'.preg_quote($this->options['whitespace_trim'].$this->options['tag_block'][1], '/').'\s*|\s*'.preg_quote($this->options['tag_block'][1], '/').')/s',
|
||||
'operator' => $this->getOperatorRegex(),
|
||||
'lex_comment' => '/(?:'.preg_quote($this->options['whitespace_trim'], '/').preg_quote($this->options['tag_comment'][1], '/').'\s*|'.preg_quote($this->options['tag_comment'][1], '/').')\n?/s',
|
||||
'lex_block_raw' => '/\s*(raw|verbatim)\s*(?:'.preg_quote($this->options['whitespace_trim'].$this->options['tag_block'][1], '/').'\s*|\s*'.preg_quote($this->options['tag_block'][1], '/').')/As',
|
||||
'lex_block_line' => '/\s*line\s+(\d+)\s*'.preg_quote($this->options['tag_block'][1], '/').'/As',
|
||||
'lex_tokens_start' => '/('.preg_quote($this->options['tag_variable'][0], '/').'|'.preg_quote($this->options['tag_block'][0], '/').'|'.preg_quote($this->options['tag_comment'][0], '/').')('.preg_quote($this->options['whitespace_trim'], '/').')?/s',
|
||||
'interpolation_start' => '/'.preg_quote($this->options['interpolation'][0], '/').'\s*/A',
|
||||
'interpolation_end' => '/\s*'.preg_quote($this->options['interpolation'][1], '/').'/A',
|
||||
'interpolation_end' => '/\s*'.preg_quote($this->options['interpolation'][1], '/').'/A',
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -287,6 +287,10 @@ class Twig_Lexer implements Twig_LexerInterface
|
|||
|
||||
protected function lexRawData($tag)
|
||||
{
|
||||
if ('raw' === $tag) {
|
||||
@trigger_error(sprintf('Twig Tag "raw" is deprecated. Use "verbatim" instead in %s at line %d.', $this->filename, $this->lineno), E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
if (!preg_match(str_replace('%s', $tag, $this->regexes['lex_raw_data']), $this->code, $match, PREG_OFFSET_CAPTURE, $this->cursor)) {
|
||||
throw new Twig_Error_Syntax(sprintf('Unexpected end of file: Unclosed "%s" block', $tag), $this->lineno, $this->filename);
|
||||
}
|
||||
|
|
@ -317,11 +321,9 @@ class Twig_Lexer implements Twig_LexerInterface
|
|||
$this->pushToken(Twig_Token::INTERPOLATION_START_TYPE);
|
||||
$this->moveCursor($match[0]);
|
||||
$this->pushState(self::STATE_INTERPOLATION);
|
||||
|
||||
} elseif (preg_match(self::REGEX_DQ_STRING_PART, $this->code, $match, null, $this->cursor) && strlen($match[0]) > 0) {
|
||||
$this->pushToken(Twig_Token::STRING_TYPE, stripcslashes($match[0]));
|
||||
$this->moveCursor($match[0]);
|
||||
|
||||
} elseif (preg_match(self::REGEX_DQ_STRING_DELIM, $this->code, $match, null, $this->cursor)) {
|
||||
list($expect, $lineno) = array_pop($this->brackets);
|
||||
if ($this->code[$this->cursor] != '"') {
|
||||
|
|
|
|||
|
|
@ -13,7 +13,8 @@
|
|||
* Interface implemented by lexer classes.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @deprecated since 1.12 (to be removed in 2.0)
|
||||
*
|
||||
* @deprecated since 1.12 (to be removed in 3.0)
|
||||
*/
|
||||
interface Twig_LexerInterface
|
||||
{
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@
|
|||
* source code of the template). If you don't want to see your cache grows out of
|
||||
* control, you need to take care of clearing the old cache file by yourself.
|
||||
*
|
||||
* This loader should only be used for unit testing.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class Twig_Loader_Array implements Twig_LoaderInterface, Twig_ExistsLoaderInterface
|
||||
|
|
@ -27,8 +29,6 @@ class Twig_Loader_Array implements Twig_LoaderInterface, Twig_ExistsLoaderInterf
|
|||
* Constructor.
|
||||
*
|
||||
* @param array $templates An array of templates (keys are the names, and values are the source code)
|
||||
*
|
||||
* @see Twig_Loader
|
||||
*/
|
||||
public function __construct(array $templates)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ class Twig_Loader_Chain implements Twig_LoaderInterface, Twig_ExistsLoaderInterf
|
|||
}
|
||||
}
|
||||
|
||||
throw new Twig_Error_Loader(sprintf('Template "%s" is not defined (%s).', $name, implode(', ', $exceptions)));
|
||||
throw new Twig_Error_Loader(sprintf('Template "%s" is not defined%s.', $name, $exceptions ? ' ('.implode(', ', $exceptions).')' : ''));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -112,7 +112,7 @@ class Twig_Loader_Chain implements Twig_LoaderInterface, Twig_ExistsLoaderInterf
|
|||
}
|
||||
}
|
||||
|
||||
throw new Twig_Error_Loader(sprintf('Template "%s" is not defined (%s).', $name, implode(' ', $exceptions)));
|
||||
throw new Twig_Error_Loader(sprintf('Template "%s" is not defined%s.', $name, $exceptions ? ' ('.implode(', ', $exceptions).')' : ''));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -133,6 +133,6 @@ class Twig_Loader_Chain implements Twig_LoaderInterface, Twig_ExistsLoaderInterf
|
|||
}
|
||||
}
|
||||
|
||||
throw new Twig_Error_Loader(sprintf('Template "%s" is not defined (%s).', $name, implode(' ', $exceptions)));
|
||||
throw new Twig_Error_Loader(sprintf('Template "%s" is not defined%s.', $name, $exceptions ? ' ('.implode(', ', $exceptions).')' : ''));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderI
|
|||
|
||||
protected $paths = array();
|
||||
protected $cache = array();
|
||||
protected $errorCache = array();
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
|
|
@ -87,7 +88,7 @@ class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderI
|
|||
public function addPath($path, $namespace = self::MAIN_NAMESPACE)
|
||||
{
|
||||
// invalidate the cache
|
||||
$this->cache = array();
|
||||
$this->cache = $this->errorCache = array();
|
||||
|
||||
if (!is_dir($path)) {
|
||||
throw new Twig_Error_Loader(sprintf('The "%s" directory does not exist.', $path));
|
||||
|
|
@ -107,7 +108,7 @@ class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderI
|
|||
public function prependPath($path, $namespace = self::MAIN_NAMESPACE)
|
||||
{
|
||||
// invalidate the cache
|
||||
$this->cache = array();
|
||||
$this->cache = $this->errorCache = array();
|
||||
|
||||
if (!is_dir($path)) {
|
||||
throw new Twig_Error_Loader(sprintf('The "%s" directory does not exist.', $path));
|
||||
|
|
@ -150,9 +151,7 @@ class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderI
|
|||
}
|
||||
|
||||
try {
|
||||
$this->findTemplate($name);
|
||||
|
||||
return true;
|
||||
return false !== $this->findTemplate($name, false);
|
||||
} catch (Twig_Error_Loader $exception) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -168,16 +167,56 @@ class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderI
|
|||
|
||||
protected function findTemplate($name)
|
||||
{
|
||||
$throw = func_num_args() > 1 ? func_get_arg(1) : true;
|
||||
$name = $this->normalizeName($name);
|
||||
|
||||
if (isset($this->cache[$name])) {
|
||||
return $this->cache[$name];
|
||||
}
|
||||
|
||||
if (isset($this->errorCache[$name])) {
|
||||
if (!$throw) {
|
||||
return false;
|
||||
}
|
||||
|
||||
throw new Twig_Error_Loader($this->errorCache[$name]);
|
||||
}
|
||||
|
||||
$this->validateName($name);
|
||||
|
||||
$namespace = self::MAIN_NAMESPACE;
|
||||
$shortname = $name;
|
||||
list($namespace, $shortname) = $this->parseName($name);
|
||||
|
||||
if (!isset($this->paths[$namespace])) {
|
||||
$this->errorCache[$name] = sprintf('There are no registered paths for namespace "%s".', $namespace);
|
||||
|
||||
if (!$throw) {
|
||||
return false;
|
||||
}
|
||||
|
||||
throw new Twig_Error_Loader($this->errorCache[$name]);
|
||||
}
|
||||
|
||||
foreach ($this->paths[$namespace] as $path) {
|
||||
if (is_file($path.'/'.$shortname)) {
|
||||
if (false !== $realpath = realpath($path.'/'.$shortname)) {
|
||||
return $this->cache[$name] = $realpath;
|
||||
}
|
||||
|
||||
return $this->cache[$name] = $path.'/'.$shortname;
|
||||
}
|
||||
}
|
||||
|
||||
$this->errorCache[$name] = sprintf('Unable to find template "%s" (looked into: %s).', $name, implode(', ', $this->paths[$namespace]));
|
||||
|
||||
if (!$throw) {
|
||||
return false;
|
||||
}
|
||||
|
||||
throw new Twig_Error_Loader($this->errorCache[$name]);
|
||||
}
|
||||
|
||||
protected function parseName($name, $default = self::MAIN_NAMESPACE)
|
||||
{
|
||||
if (isset($name[0]) && '@' == $name[0]) {
|
||||
if (false === $pos = strpos($name, '/')) {
|
||||
throw new Twig_Error_Loader(sprintf('Malformed namespaced template name "%s" (expecting "@namespace/template_name").', $name));
|
||||
|
|
@ -185,24 +224,16 @@ class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderI
|
|||
|
||||
$namespace = substr($name, 1, $pos - 1);
|
||||
$shortname = substr($name, $pos + 1);
|
||||
|
||||
return array($namespace, $shortname);
|
||||
}
|
||||
|
||||
if (!isset($this->paths[$namespace])) {
|
||||
throw new Twig_Error_Loader(sprintf('There are no registered paths for namespace "%s".', $namespace));
|
||||
}
|
||||
|
||||
foreach ($this->paths[$namespace] as $path) {
|
||||
if (is_file($path.'/'.$shortname)) {
|
||||
return $this->cache[$name] = $path.'/'.$shortname;
|
||||
}
|
||||
}
|
||||
|
||||
throw new Twig_Error_Loader(sprintf('Unable to find template "%s" (looked into: %s).', $name, implode(', ', $this->paths[$namespace])));
|
||||
return array($default, $name);
|
||||
}
|
||||
|
||||
protected function normalizeName($name)
|
||||
{
|
||||
return preg_replace('#/{2,}#', '/', strtr((string) $name, '\\', '/'));
|
||||
return preg_replace('#/{2,}#', '/', str_replace('\\', '/', (string) $name));
|
||||
}
|
||||
|
||||
protected function validateName($name)
|
||||
|
|
|
|||
|
|
@ -9,18 +9,22 @@
|
|||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
@trigger_error('The Twig_Loader_String class is deprecated since version 1.18.1 and will be removed in 2.0. Use Twig_Loader_Array instead or Twig_Environment::createTemplate().', E_USER_DEPRECATED);
|
||||
|
||||
/**
|
||||
* Loads a template from a string.
|
||||
*
|
||||
* This loader should only be used for unit testing as it has many limitations
|
||||
* (for instance, the include or extends tag does not make any sense for a string
|
||||
* loader).
|
||||
* This loader should NEVER be used. It only exists for Twig internal purposes.
|
||||
*
|
||||
* When using this loader with a cache mechanism, you should know that a new cache
|
||||
* key is generated each time a template content "changes" (the cache key being the
|
||||
* source code of the template). If you don't want to see your cache grows out of
|
||||
* control, you need to take care of clearing the old cache file by yourself.
|
||||
*
|
||||
* @deprecated since 1.18.1 (to be removed in 2.0)
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class Twig_Loader_String implements Twig_LoaderInterface, Twig_ExistsLoaderInterface
|
||||
|
|
|
|||
|
|
@ -41,10 +41,11 @@ interface Twig_LoaderInterface
|
|||
/**
|
||||
* Returns true if the template is still fresh.
|
||||
*
|
||||
* @param string $name The template name
|
||||
* @param timestamp $time The last modification time of the cached template
|
||||
* @param string $name The template name
|
||||
* @param int $time Timestamp of the last modification time of the
|
||||
* cached template
|
||||
*
|
||||
* @return Boolean true if the template is fresh, false otherwise
|
||||
* @return bool true if the template is fresh, false otherwise
|
||||
*
|
||||
* @throws Twig_Error_Loader When $name is not found
|
||||
*/
|
||||
|
|
|
|||
49
www/analytics/vendor/twig/twig/lib/Twig/Node.php
vendored
49
www/analytics/vendor/twig/twig/lib/Twig/Node.php
vendored
|
|
@ -28,10 +28,10 @@ class Twig_Node implements Twig_NodeInterface
|
|||
* The nodes are automatically made available as properties ($this->node).
|
||||
* The attributes are automatically made available as array items ($this['name']).
|
||||
*
|
||||
* @param array $nodes An array of named nodes
|
||||
* @param array $attributes An array of attributes (should not be nodes)
|
||||
* @param integer $lineno The line number
|
||||
* @param string $tag The tag name associated with the Node
|
||||
* @param array $nodes An array of named nodes
|
||||
* @param array $attributes An array of attributes (should not be nodes)
|
||||
* @param int $lineno The line number
|
||||
* @param string $tag The tag name associated with the Node
|
||||
*/
|
||||
public function __construct(array $nodes = array(), array $attributes = array(), $lineno = 0, $tag = null)
|
||||
{
|
||||
|
|
@ -69,8 +69,13 @@ class Twig_Node implements Twig_NodeInterface
|
|||
return implode("\n", $repr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated since 1.16.1 (to be removed in 2.0)
|
||||
*/
|
||||
public function toXml($asDom = false)
|
||||
{
|
||||
@trigger_error(sprintf('%s is deprecated.', __METHOD__), E_USER_DEPRECATED);
|
||||
|
||||
$dom = new DOMDocument('1.0', 'UTF-8');
|
||||
$dom->formatOutput = true;
|
||||
$dom->appendChild($xml = $dom->createElement('twig'));
|
||||
|
|
@ -119,9 +124,9 @@ class Twig_Node implements Twig_NodeInterface
|
|||
/**
|
||||
* Returns true if the attribute is defined.
|
||||
*
|
||||
* @param string The attribute name
|
||||
* @param string $name The attribute name
|
||||
*
|
||||
* @return Boolean true if the attribute is defined, false otherwise
|
||||
* @return bool true if the attribute is defined, false otherwise
|
||||
*/
|
||||
public function hasAttribute($name)
|
||||
{
|
||||
|
|
@ -129,11 +134,11 @@ class Twig_Node implements Twig_NodeInterface
|
|||
}
|
||||
|
||||
/**
|
||||
* Gets an attribute.
|
||||
* Gets an attribute value by name.
|
||||
*
|
||||
* @param string The attribute name
|
||||
* @param string $name
|
||||
*
|
||||
* @return mixed The attribute value
|
||||
* @return mixed
|
||||
*/
|
||||
public function getAttribute($name)
|
||||
{
|
||||
|
|
@ -145,10 +150,10 @@ class Twig_Node implements Twig_NodeInterface
|
|||
}
|
||||
|
||||
/**
|
||||
* Sets an attribute.
|
||||
* Sets an attribute by name to a value.
|
||||
*
|
||||
* @param string The attribute name
|
||||
* @param mixed The attribute value
|
||||
* @param string $name
|
||||
* @param mixed $value
|
||||
*/
|
||||
public function setAttribute($name, $value)
|
||||
{
|
||||
|
|
@ -156,9 +161,9 @@ class Twig_Node implements Twig_NodeInterface
|
|||
}
|
||||
|
||||
/**
|
||||
* Removes an attribute.
|
||||
* Removes an attribute by name.
|
||||
*
|
||||
* @param string The attribute name
|
||||
* @param string $name
|
||||
*/
|
||||
public function removeAttribute($name)
|
||||
{
|
||||
|
|
@ -166,11 +171,11 @@ class Twig_Node implements Twig_NodeInterface
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns true if the node with the given identifier exists.
|
||||
* Returns true if the node with the given name exists.
|
||||
*
|
||||
* @param string The node name
|
||||
* @param string $name
|
||||
*
|
||||
* @return Boolean true if the node with the given name exists, false otherwise
|
||||
* @return bool
|
||||
*/
|
||||
public function hasNode($name)
|
||||
{
|
||||
|
|
@ -180,9 +185,9 @@ class Twig_Node implements Twig_NodeInterface
|
|||
/**
|
||||
* Gets a node by name.
|
||||
*
|
||||
* @param string The node name
|
||||
* @param string $name
|
||||
*
|
||||
* @return Twig_Node A Twig_Node instance
|
||||
* @return Twig_Node
|
||||
*/
|
||||
public function getNode($name)
|
||||
{
|
||||
|
|
@ -196,8 +201,8 @@ class Twig_Node implements Twig_NodeInterface
|
|||
/**
|
||||
* Sets a node.
|
||||
*
|
||||
* @param string The node name
|
||||
* @param Twig_Node A Twig_Node instance
|
||||
* @param string $name
|
||||
* @param Twig_Node $node
|
||||
*/
|
||||
public function setNode($name, $node = null)
|
||||
{
|
||||
|
|
@ -207,7 +212,7 @@ class Twig_Node implements Twig_NodeInterface
|
|||
/**
|
||||
* Removes a node by name.
|
||||
*
|
||||
* @param string The node name
|
||||
* @param string $name
|
||||
*/
|
||||
public function removeNode($name)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ class Twig_Node_AutoEscape extends Twig_Node
|
|||
/**
|
||||
* Compiles the node to PHP.
|
||||
*
|
||||
* @param Twig_Compiler A Twig_Compiler instance
|
||||
* @param Twig_Compiler $compiler A Twig_Compiler instance
|
||||
*/
|
||||
public function compile(Twig_Compiler $compiler)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ class Twig_Node_Block extends Twig_Node
|
|||
/**
|
||||
* Compiles the node to PHP.
|
||||
*
|
||||
* @param Twig_Compiler A Twig_Compiler instance
|
||||
* @param Twig_Compiler $compiler A Twig_Compiler instance
|
||||
*/
|
||||
public function compile(Twig_Compiler $compiler)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ class Twig_Node_BlockReference extends Twig_Node implements Twig_NodeOutputInter
|
|||
/**
|
||||
* Compiles the node to PHP.
|
||||
*
|
||||
* @param Twig_Compiler A Twig_Compiler instance
|
||||
* @param Twig_Compiler $compiler A Twig_Compiler instance
|
||||
*/
|
||||
public function compile(Twig_Compiler $compiler)
|
||||
{
|
||||
|
|
|
|||
78
www/analytics/vendor/twig/twig/lib/Twig/Node/CheckSecurity.php
vendored
Normal file
78
www/analytics/vendor/twig/twig/lib/Twig/Node/CheckSecurity.php
vendored
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2015 Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class Twig_Node_CheckSecurity extends Twig_Node
|
||||
{
|
||||
protected $usedFilters;
|
||||
protected $usedTags;
|
||||
protected $usedFunctions;
|
||||
|
||||
public function __construct(array $usedFilters, array $usedTags, array $usedFunctions)
|
||||
{
|
||||
$this->usedFilters = $usedFilters;
|
||||
$this->usedTags = $usedTags;
|
||||
$this->usedFunctions = $usedFunctions;
|
||||
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
public function compile(Twig_Compiler $compiler)
|
||||
{
|
||||
$tags = $filters = $functions = array();
|
||||
foreach (array('tags', 'filters', 'functions') as $type) {
|
||||
foreach ($this->{'used'.ucfirst($type)} as $name => $node) {
|
||||
if ($node instanceof Twig_Node) {
|
||||
${$type}[$name] = $node->getLine();
|
||||
} else {
|
||||
${$type}[$node] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$compiler
|
||||
->write('$tags = ')->repr(array_filter($tags))->raw(";\n")
|
||||
->write('$filters = ')->repr(array_filter($filters))->raw(";\n")
|
||||
->write('$functions = ')->repr(array_filter($functions))->raw(";\n\n")
|
||||
->write("try {\n")
|
||||
->indent()
|
||||
->write("\$this->env->getExtension('sandbox')->checkSecurity(\n")
|
||||
->indent()
|
||||
->write(!$tags ? "array(),\n" : "array('".implode("', '", array_keys($tags))."'),\n")
|
||||
->write(!$filters ? "array(),\n" : "array('".implode("', '", array_keys($filters))."'),\n")
|
||||
->write(!$functions ? "array()\n" : "array('".implode("', '", array_keys($functions))."')\n")
|
||||
->outdent()
|
||||
->write(");\n")
|
||||
->outdent()
|
||||
->write("} catch (Twig_Sandbox_SecurityError \$e) {\n")
|
||||
->indent()
|
||||
->write("\$e->setTemplateFile(\$this->getTemplateName());\n\n")
|
||||
->write("if (\$e instanceof Twig_Sandbox_SecurityNotAllowedTagError && isset(\$tags[\$e->getTagName()])) {\n")
|
||||
->indent()
|
||||
->write("\$e->setTemplateLine(\$tags[\$e->getTagName()]);\n")
|
||||
->outdent()
|
||||
->write("} elseif (\$e instanceof Twig_Sandbox_SecurityNotAllowedFilterError && isset(\$filters[\$e->getFilterName()])) {\n")
|
||||
->indent()
|
||||
->write("\$e->setTemplateLine(\$filters[\$e->getFilterName()]);\n")
|
||||
->outdent()
|
||||
->write("} elseif (\$e instanceof Twig_Sandbox_SecurityNotAllowedFunctionError && isset(\$functions[\$e->getFunctionName()])) {\n")
|
||||
->indent()
|
||||
->write("\$e->setTemplateLine(\$functions[\$e->getFunctionName()]);\n")
|
||||
->outdent()
|
||||
->write("}\n\n")
|
||||
->write("throw \$e;\n")
|
||||
->outdent()
|
||||
->write("}\n\n")
|
||||
;
|
||||
}
|
||||
}
|
||||
|
|
@ -24,7 +24,7 @@ class Twig_Node_Do extends Twig_Node
|
|||
/**
|
||||
* Compiles the node to PHP.
|
||||
*
|
||||
* @param Twig_Compiler A Twig_Compiler instance
|
||||
* @param Twig_Compiler $compiler A Twig_Compiler instance
|
||||
*/
|
||||
public function compile(Twig_Compiler $compiler)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -28,11 +28,15 @@ class Twig_Node_Embed extends Twig_Node_Include
|
|||
protected function addGetTemplate(Twig_Compiler $compiler)
|
||||
{
|
||||
$compiler
|
||||
->write("\$this->env->loadTemplate(")
|
||||
->write('$this->loadTemplate(')
|
||||
->string($this->getAttribute('filename'))
|
||||
->raw(', ')
|
||||
->repr($compiler->getFilename())
|
||||
->raw(', ')
|
||||
->repr($this->getLine())
|
||||
->raw(', ')
|
||||
->string($this->getAttribute('index'))
|
||||
->raw(")")
|
||||
->raw(')')
|
||||
;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ class Twig_Node_Expression_Array extends Twig_Node_Expression
|
|||
/**
|
||||
* Compiles the node to PHP.
|
||||
*
|
||||
* @param Twig_Compiler A Twig_Compiler instance
|
||||
* @param Twig_Compiler $compiler A Twig_Compiler instance
|
||||
*/
|
||||
public function compile(Twig_Compiler $compiler)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ class Twig_Node_Expression_AssignName extends Twig_Node_Expression_Name
|
|||
/**
|
||||
* Compiles the node to PHP.
|
||||
*
|
||||
* @param Twig_Compiler A Twig_Compiler instance
|
||||
* @param Twig_Compiler $compiler A Twig_Compiler instance
|
||||
*/
|
||||
public function compile(Twig_Compiler $compiler)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ abstract class Twig_Node_Expression_Binary extends Twig_Node_Expression
|
|||
/**
|
||||
* Compiles the node to PHP.
|
||||
*
|
||||
* @param Twig_Compiler A Twig_Compiler instance
|
||||
* @param Twig_Compiler $compiler A Twig_Compiler instance
|
||||
*/
|
||||
public function compile(Twig_Compiler $compiler)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -12,14 +12,14 @@ class Twig_Node_Expression_Binary_EndsWith extends Twig_Node_Expression_Binary
|
|||
{
|
||||
public function compile(Twig_Compiler $compiler)
|
||||
{
|
||||
$left = $compiler->getVarName();
|
||||
$right = $compiler->getVarName();
|
||||
$compiler
|
||||
->raw('(0 === substr_compare(')
|
||||
->raw(sprintf('(is_string($%s = ', $left))
|
||||
->subcompile($this->getNode('left'))
|
||||
->raw(', ')
|
||||
->raw(sprintf(') && is_string($%s = ', $right))
|
||||
->subcompile($this->getNode('right'))
|
||||
->raw(', -strlen(')
|
||||
->subcompile($this->getNode('right'))
|
||||
->raw(')))')
|
||||
->raw(sprintf(') && (\'\' === $%2$s || $%2$s === substr($%1$s, -strlen($%2$s))))', $left, $right))
|
||||
;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ class Twig_Node_Expression_Binary_FloorDiv extends Twig_Node_Expression_Binary
|
|||
/**
|
||||
* Compiles the node to PHP.
|
||||
*
|
||||
* @param Twig_Compiler A Twig_Compiler instance
|
||||
* @param Twig_Compiler $compiler A Twig_Compiler instance
|
||||
*/
|
||||
public function compile(Twig_Compiler $compiler)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ class Twig_Node_Expression_Binary_In extends Twig_Node_Expression_Binary
|
|||
/**
|
||||
* Compiles the node to PHP.
|
||||
*
|
||||
* @param Twig_Compiler A Twig_Compiler instance
|
||||
* @param Twig_Compiler $compiler A Twig_Compiler instance
|
||||
*/
|
||||
public function compile(Twig_Compiler $compiler)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ class Twig_Node_Expression_Binary_NotIn extends Twig_Node_Expression_Binary
|
|||
/**
|
||||
* Compiles the node to PHP.
|
||||
*
|
||||
* @param Twig_Compiler A Twig_Compiler instance
|
||||
* @param Twig_Compiler $compiler A Twig_Compiler instance
|
||||
*/
|
||||
public function compile(Twig_Compiler $compiler)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ class Twig_Node_Expression_Binary_Power extends Twig_Node_Expression_Binary
|
|||
/**
|
||||
* Compiles the node to PHP.
|
||||
*
|
||||
* @param Twig_Compiler A Twig_Compiler instance
|
||||
* @param Twig_Compiler $compiler A Twig_Compiler instance
|
||||
*/
|
||||
public function compile(Twig_Compiler $compiler)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ class Twig_Node_Expression_Binary_Range extends Twig_Node_Expression_Binary
|
|||
/**
|
||||
* Compiles the node to PHP.
|
||||
*
|
||||
* @param Twig_Compiler A Twig_Compiler instance
|
||||
* @param Twig_Compiler $compiler A Twig_Compiler instance
|
||||
*/
|
||||
public function compile(Twig_Compiler $compiler)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -12,12 +12,14 @@ class Twig_Node_Expression_Binary_StartsWith extends Twig_Node_Expression_Binary
|
|||
{
|
||||
public function compile(Twig_Compiler $compiler)
|
||||
{
|
||||
$left = $compiler->getVarName();
|
||||
$right = $compiler->getVarName();
|
||||
$compiler
|
||||
->raw('(0 === strpos(')
|
||||
->raw(sprintf('(is_string($%s = ', $left))
|
||||
->subcompile($this->getNode('left'))
|
||||
->raw(', ')
|
||||
->raw(sprintf(') && is_string($%s = ', $right))
|
||||
->subcompile($this->getNode('right'))
|
||||
->raw('))')
|
||||
->raw(sprintf(') && (\'\' === $%2$s || 0 === strpos($%1$s, $%2$s)))', $left, $right))
|
||||
;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ class Twig_Node_Expression_BlockReference extends Twig_Node_Expression
|
|||
/**
|
||||
* Compiles the node to PHP.
|
||||
*
|
||||
* @param Twig_Compiler A Twig_Compiler instance
|
||||
* @param Twig_Compiler $compiler A Twig_Compiler instance
|
||||
*/
|
||||
public function compile(Twig_Compiler $compiler)
|
||||
{
|
||||
|
|
@ -36,15 +36,15 @@ class Twig_Node_Expression_BlockReference extends Twig_Node_Expression
|
|||
if ($this->getAttribute('output')) {
|
||||
$compiler
|
||||
->addDebugInfo($this)
|
||||
->write("\$this->displayBlock(")
|
||||
->write('$this->displayBlock(')
|
||||
->subcompile($this->getNode('name'))
|
||||
->raw(", \$context, \$blocks);\n")
|
||||
;
|
||||
} else {
|
||||
$compiler
|
||||
->raw("\$this->renderBlock(")
|
||||
->raw('$this->renderBlock(')
|
||||
->subcompile($this->getNode('name'))
|
||||
->raw(", \$context, \$blocks)")
|
||||
->raw(', $context, $blocks)')
|
||||
;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,10 +12,8 @@ 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 ($this->hasAttribute('callable') && $callable = $this->getAttribute('callable')) {
|
||||
if (is_string($callable)) {
|
||||
$compiler->raw($callable);
|
||||
} elseif (is_array($callable) && $callable[0] instanceof Twig_ExtensionInterface) {
|
||||
|
|
@ -92,6 +90,9 @@ abstract class Twig_Node_Expression_Call extends Twig_Node_Expression
|
|||
|
||||
protected function getArguments($callable, $arguments)
|
||||
{
|
||||
$callType = $this->getAttribute('type');
|
||||
$callName = $this->getAttribute('name');
|
||||
|
||||
$parameters = array();
|
||||
$named = false;
|
||||
foreach ($arguments as $name => $node) {
|
||||
|
|
@ -99,18 +100,25 @@ abstract class Twig_Node_Expression_Call extends Twig_Node_Expression
|
|||
$named = true;
|
||||
$name = $this->normalizeName($name);
|
||||
} elseif ($named) {
|
||||
throw new Twig_Error_Syntax(sprintf('Positional arguments cannot be used after named arguments for %s "%s".', $this->getAttribute('type'), $this->getAttribute('name')));
|
||||
throw new Twig_Error_Syntax(sprintf('Positional arguments cannot be used after named arguments for %s "%s".', $callType, $callName));
|
||||
}
|
||||
|
||||
$parameters[$name] = $node;
|
||||
}
|
||||
|
||||
if (!$named) {
|
||||
$isVariadic = $this->hasAttribute('is_variadic') && $this->getAttribute('is_variadic');
|
||||
if (!$named && !$isVariadic) {
|
||||
return $parameters;
|
||||
}
|
||||
|
||||
if (!$callable) {
|
||||
throw new LogicException(sprintf('Named arguments are not supported for %s "%s".', $this->getAttribute('type'), $this->getAttribute('name')));
|
||||
if ($named) {
|
||||
$message = sprintf('Named arguments are not supported for %s "%s".', $callType, $callName);
|
||||
} else {
|
||||
$message = sprintf('Arbitrary positional arguments are not supported for %s "%s".', $callType, $callName);
|
||||
}
|
||||
|
||||
throw new LogicException($message);
|
||||
}
|
||||
|
||||
// manage named arguments
|
||||
|
|
@ -119,6 +127,8 @@ abstract class Twig_Node_Expression_Call extends Twig_Node_Expression
|
|||
} elseif (is_object($callable) && !$callable instanceof Closure) {
|
||||
$r = new ReflectionObject($callable);
|
||||
$r = $r->getMethod('__invoke');
|
||||
} elseif (is_string($callable) && false !== strpos($callable, '::')) {
|
||||
$r = new ReflectionMethod($callable);
|
||||
} else {
|
||||
$r = new ReflectionFunction($callable);
|
||||
}
|
||||
|
|
@ -138,34 +148,93 @@ abstract class Twig_Node_Expression_Call extends Twig_Node_Expression
|
|||
array_shift($definition);
|
||||
}
|
||||
}
|
||||
if ($isVariadic) {
|
||||
$argument = end($definition);
|
||||
if ($argument && $argument->isArray() && $argument->isDefaultValueAvailable() && array() === $argument->getDefaultValue()) {
|
||||
array_pop($definition);
|
||||
} else {
|
||||
$callableName = $r->name;
|
||||
if ($r->getDeclaringClass()) {
|
||||
$callableName = $r->getDeclaringClass()->name.'::'.$callableName;
|
||||
}
|
||||
|
||||
throw new LogicException(sprintf('The last parameter of "%s" for %s "%s" must be an array with default value, eg. "array $arg = array()".', $callableName, $callType, $callName));
|
||||
}
|
||||
}
|
||||
|
||||
$arguments = array();
|
||||
$names = array();
|
||||
$missingArguments = array();
|
||||
$optionalArguments = array();
|
||||
$pos = 0;
|
||||
foreach ($definition as $param) {
|
||||
$name = $this->normalizeName($param->name);
|
||||
$names[] = $name = $this->normalizeName($param->name);
|
||||
|
||||
if (array_key_exists($name, $parameters)) {
|
||||
if (array_key_exists($pos, $parameters)) {
|
||||
throw new Twig_Error_Syntax(sprintf('Argument "%s" is defined twice for %s "%s".', $name, $this->getAttribute('type'), $this->getAttribute('name')));
|
||||
throw new Twig_Error_Syntax(sprintf('Argument "%s" is defined twice for %s "%s".', $name, $callType, $callName));
|
||||
}
|
||||
|
||||
if (!empty($missingArguments)) {
|
||||
throw new Twig_Error_Syntax(sprintf(
|
||||
'Argument "%s" could not be assigned for %s "%s(%s)" because it is mapped to an internal PHP function which cannot determine default value for optional argument%s "%s".',
|
||||
$name, $callType, $callName, implode(', ', $names), count($missingArguments) > 1 ? 's' : '', implode('", "', $missingArguments))
|
||||
);
|
||||
}
|
||||
|
||||
$arguments = array_merge($arguments, $optionalArguments);
|
||||
$arguments[] = $parameters[$name];
|
||||
unset($parameters[$name]);
|
||||
$optionalArguments = array();
|
||||
} elseif (array_key_exists($pos, $parameters)) {
|
||||
$arguments = array_merge($arguments, $optionalArguments);
|
||||
$arguments[] = $parameters[$pos];
|
||||
unset($parameters[$pos]);
|
||||
$optionalArguments = array();
|
||||
++$pos;
|
||||
} elseif ($param->isDefaultValueAvailable()) {
|
||||
$arguments[] = new Twig_Node_Expression_Constant($param->getDefaultValue(), -1);
|
||||
$optionalArguments[] = new Twig_Node_Expression_Constant($param->getDefaultValue(), -1);
|
||||
} elseif ($param->isOptional()) {
|
||||
break;
|
||||
if (empty($parameters)) {
|
||||
break;
|
||||
} else {
|
||||
$missingArguments[] = $name;
|
||||
}
|
||||
} else {
|
||||
throw new Twig_Error_Syntax(sprintf('Value for argument "%s" is required for %s "%s".', $name, $this->getAttribute('type'), $this->getAttribute('name')));
|
||||
throw new Twig_Error_Syntax(sprintf('Value for argument "%s" is required for %s "%s".', $name, $callType, $callName));
|
||||
}
|
||||
}
|
||||
|
||||
if ($isVariadic) {
|
||||
$arbitraryArguments = new Twig_Node_Expression_Array(array(), -1);
|
||||
foreach ($parameters as $key => $value) {
|
||||
if (is_int($key)) {
|
||||
$arbitraryArguments->addElement($value);
|
||||
} else {
|
||||
$arbitraryArguments->addElement($value, new Twig_Node_Expression_Constant($key, -1));
|
||||
}
|
||||
unset($parameters[$key]);
|
||||
}
|
||||
|
||||
if ($arbitraryArguments->count()) {
|
||||
$arguments = array_merge($arguments, $optionalArguments);
|
||||
$arguments[] = $arbitraryArguments;
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($parameters)) {
|
||||
throw new Twig_Error_Syntax(sprintf('Unknown argument%s "%s" for %s "%s".', count($parameters) > 1 ? 's' : '', implode('", "', array_keys($parameters)), $this->getAttribute('type'), $this->getAttribute('name')));
|
||||
$unknownParameter = null;
|
||||
foreach ($parameters as $parameter) {
|
||||
if ($parameter instanceof Twig_Node) {
|
||||
$unknownParameter = $parameter;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
throw new Twig_Error_Syntax(sprintf(
|
||||
'Unknown argument%s "%s" for %s "%s(%s)".',
|
||||
count($parameters) > 1 ? 's' : '', implode('", "', array_keys($parameters)), $callType, $callName, implode(', ', $names)
|
||||
), $unknownParameter ? $unknownParameter->getLine() : -1);
|
||||
}
|
||||
|
||||
return $arguments;
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ class Twig_Node_Expression_ExtensionReference extends Twig_Node_Expression
|
|||
/**
|
||||
* Compiles the node to PHP.
|
||||
*
|
||||
* @param Twig_Compiler A Twig_Compiler instance
|
||||
* @param Twig_Compiler $compiler A Twig_Compiler instance
|
||||
*/
|
||||
public function compile(Twig_Compiler $compiler)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -30,6 +30,9 @@ class Twig_Node_Expression_Filter extends Twig_Node_Expression_Call
|
|||
if ($filter instanceof Twig_FilterCallableInterface || $filter instanceof Twig_SimpleFilter) {
|
||||
$this->setAttribute('callable', $filter->getCallable());
|
||||
}
|
||||
if ($filter instanceof Twig_SimpleFilter) {
|
||||
$this->setAttribute('is_variadic', $filter->isVariadic());
|
||||
}
|
||||
|
||||
$this->compileCallable($compiler);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,9 @@ class Twig_Node_Expression_Function extends Twig_Node_Expression_Call
|
|||
if ($function instanceof Twig_FunctionCallableInterface || $function instanceof Twig_SimpleFunction) {
|
||||
$this->setAttribute('callable', $function->getCallable());
|
||||
}
|
||||
if ($function instanceof Twig_SimpleFunction) {
|
||||
$this->setAttribute('is_variadic', $function->isVariadic());
|
||||
}
|
||||
|
||||
$this->compileCallable($compiler);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
*/
|
||||
class Twig_Node_Expression_GetAttr extends Twig_Node_Expression
|
||||
{
|
||||
public function __construct(Twig_Node_Expression $node, Twig_Node_Expression $attribute, Twig_Node_Expression_Array $arguments, $type, $lineno)
|
||||
public function __construct(Twig_Node_Expression $node, Twig_Node_Expression $attribute, Twig_Node_Expression $arguments = null, $type, $lineno)
|
||||
{
|
||||
parent::__construct(array('node' => $node, 'attribute' => $attribute, 'arguments' => $arguments), array('type' => $type, 'is_defined_test' => false, 'ignore_strict_check' => false, 'disable_c_ext' => false), $lineno);
|
||||
}
|
||||
|
|
@ -32,20 +32,30 @@ class Twig_Node_Expression_GetAttr extends Twig_Node_Expression
|
|||
|
||||
$compiler->raw(', ')->subcompile($this->getNode('attribute'));
|
||||
|
||||
if (count($this->getNode('arguments')) || Twig_Template::ANY_CALL !== $this->getAttribute('type') || $this->getAttribute('is_defined_test') || $this->getAttribute('ignore_strict_check')) {
|
||||
$compiler->raw(', ')->subcompile($this->getNode('arguments'));
|
||||
// only generate optional arguments when needed (to make generated code more readable)
|
||||
$needFourth = $this->getAttribute('ignore_strict_check');
|
||||
$needThird = $needFourth || $this->getAttribute('is_defined_test');
|
||||
$needSecond = $needThird || Twig_Template::ANY_CALL !== $this->getAttribute('type');
|
||||
$needFirst = $needSecond || null !== $this->getNode('arguments');
|
||||
|
||||
if (Twig_Template::ANY_CALL !== $this->getAttribute('type') || $this->getAttribute('is_defined_test') || $this->getAttribute('ignore_strict_check')) {
|
||||
$compiler->raw(', ')->repr($this->getAttribute('type'));
|
||||
if ($needFirst) {
|
||||
if (null !== $this->getNode('arguments')) {
|
||||
$compiler->raw(', ')->subcompile($this->getNode('arguments'));
|
||||
} else {
|
||||
$compiler->raw(', array()');
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->getAttribute('is_defined_test') || $this->getAttribute('ignore_strict_check')) {
|
||||
$compiler->raw(', '.($this->getAttribute('is_defined_test') ? 'true' : 'false'));
|
||||
}
|
||||
if ($needSecond) {
|
||||
$compiler->raw(', ')->repr($this->getAttribute('type'));
|
||||
}
|
||||
|
||||
if ($this->getAttribute('ignore_strict_check')) {
|
||||
$compiler->raw(', '.($this->getAttribute('ignore_strict_check') ? 'true' : 'false'));
|
||||
}
|
||||
if ($needThird) {
|
||||
$compiler->raw(', ')->repr($this->getAttribute('is_defined_test'));
|
||||
}
|
||||
|
||||
if ($needFourth) {
|
||||
$compiler->raw(', ')->repr($this->getAttribute('ignore_strict_check'));
|
||||
}
|
||||
|
||||
$compiler->raw(')');
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
class Twig_Node_Expression_Name extends Twig_Node_Expression
|
||||
{
|
||||
protected $specialVars = array(
|
||||
'_self' => '$this',
|
||||
'_self' => '$this',
|
||||
'_context' => '$context',
|
||||
'_charset' => '$this->env->getCharset()',
|
||||
);
|
||||
|
|
@ -26,13 +26,23 @@ class Twig_Node_Expression_Name extends Twig_Node_Expression
|
|||
{
|
||||
$name = $this->getAttribute('name');
|
||||
|
||||
$compiler->addDebugInfo($this);
|
||||
|
||||
if ($this->getAttribute('is_defined_test')) {
|
||||
if ($this->isSpecial()) {
|
||||
if ('_self' === $name) {
|
||||
@trigger_error(sprintf('Global variable "_self" is deprecated in %s at line %d', '?', $this->getLine()), E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
$compiler->repr(true);
|
||||
} else {
|
||||
$compiler->raw('array_key_exists(')->repr($name)->raw(', $context)');
|
||||
}
|
||||
} elseif ($this->isSpecial()) {
|
||||
if ('_self' === $name) {
|
||||
@trigger_error(sprintf('Global variable "_self" is deprecated in %s at line %d', '?', $this->getLine()), E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
$compiler->raw($this->specialVars[$name]);
|
||||
} elseif ($this->getAttribute('always_defined')) {
|
||||
$compiler
|
||||
|
|
@ -44,7 +54,7 @@ class Twig_Node_Expression_Name extends Twig_Node_Expression
|
|||
// remove the non-PHP 5.4 version when PHP 5.3 support is dropped
|
||||
// as the non-optimized version is just a workaround for slow ternary operator
|
||||
// when the context has a lot of variables
|
||||
if (version_compare(phpversion(), '5.4.0RC1', '>=')) {
|
||||
if (PHP_VERSION_ID >= 50400) {
|
||||
// PHP 5.4 ternary operator performance was optimized
|
||||
$compiler
|
||||
->raw('(isset($context[')
|
||||
|
|
|
|||
|
|
@ -25,22 +25,22 @@ class Twig_Node_Expression_Parent extends Twig_Node_Expression
|
|||
/**
|
||||
* Compiles the node to PHP.
|
||||
*
|
||||
* @param Twig_Compiler A Twig_Compiler instance
|
||||
* @param Twig_Compiler $compiler A Twig_Compiler instance
|
||||
*/
|
||||
public function compile(Twig_Compiler $compiler)
|
||||
{
|
||||
if ($this->getAttribute('output')) {
|
||||
$compiler
|
||||
->addDebugInfo($this)
|
||||
->write("\$this->displayParentBlock(")
|
||||
->write('$this->displayParentBlock(')
|
||||
->string($this->getAttribute('name'))
|
||||
->raw(", \$context, \$blocks);\n")
|
||||
;
|
||||
} else {
|
||||
$compiler
|
||||
->raw("\$this->renderParentBlock(")
|
||||
->raw('$this->renderParentBlock(')
|
||||
->string($this->getAttribute('name'))
|
||||
->raw(", \$context, \$blocks)")
|
||||
->raw(', $context, $blocks)')
|
||||
;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,9 @@ class Twig_Node_Expression_Test extends Twig_Node_Expression_Call
|
|||
if ($test instanceof Twig_TestCallableInterface || $test instanceof Twig_SimpleTest) {
|
||||
$this->setAttribute('callable', $test->getCallable());
|
||||
}
|
||||
if ($test instanceof Twig_SimpleTest) {
|
||||
$this->setAttribute('is_variadic', $test->isVariadic());
|
||||
}
|
||||
|
||||
$this->compileCallable($compiler);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
* Checks if a variable is divisible by a number.
|
||||
*
|
||||
* <pre>
|
||||
* {% if loop.index is divisibleby(3) %}
|
||||
* {% if loop.index is divisible by(3) %}
|
||||
* </pre>
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
|
|
|
|||
|
|
@ -18,12 +18,9 @@ abstract class Twig_Node_Expression_Unary extends Twig_Node_Expression
|
|||
|
||||
public function compile(Twig_Compiler $compiler)
|
||||
{
|
||||
$compiler->raw('(');
|
||||
$compiler->raw(' ');
|
||||
$this->operator($compiler);
|
||||
$compiler
|
||||
->subcompile($this->getNode('node'))
|
||||
->raw(')')
|
||||
;
|
||||
$compiler->subcompile($this->getNode('node'));
|
||||
}
|
||||
|
||||
abstract public function operator(Twig_Compiler $compiler);
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ class Twig_Node_Flush extends Twig_Node
|
|||
/**
|
||||
* Compiles the node to PHP.
|
||||
*
|
||||
* @param Twig_Compiler A Twig_Compiler instance
|
||||
* @param Twig_Compiler $compiler A Twig_Compiler instance
|
||||
*/
|
||||
public function compile(Twig_Compiler $compiler)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -33,14 +33,13 @@ class Twig_Node_For extends Twig_Node
|
|||
/**
|
||||
* Compiles the node to PHP.
|
||||
*
|
||||
* @param Twig_Compiler A Twig_Compiler instance
|
||||
* @param Twig_Compiler $compiler A Twig_Compiler instance
|
||||
*/
|
||||
public function compile(Twig_Compiler $compiler)
|
||||
{
|
||||
$compiler
|
||||
->addDebugInfo($this)
|
||||
// the (array) cast bypasses a PHP 5.2.6 bug
|
||||
->write("\$context['_parent'] = (array) \$context;\n")
|
||||
->write("\$context['_parent'] = \$context;\n")
|
||||
->write("\$context['_seq'] = twig_ensure_traversable(")
|
||||
->subcompile($this->getNode('seq'))
|
||||
->raw(");\n")
|
||||
|
|
@ -82,7 +81,7 @@ class Twig_Node_For extends Twig_Node
|
|||
$compiler
|
||||
->write("foreach (\$context['_seq'] as ")
|
||||
->subcompile($this->getNode('key_target'))
|
||||
->raw(" => ")
|
||||
->raw(' => ')
|
||||
->subcompile($this->getNode('value_target'))
|
||||
->raw(") {\n")
|
||||
->indent()
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ class Twig_Node_ForLoop extends Twig_Node
|
|||
/**
|
||||
* Compiles the node to PHP.
|
||||
*
|
||||
* @param Twig_Compiler A Twig_Compiler instance
|
||||
* @param Twig_Compiler $compiler A Twig_Compiler instance
|
||||
*/
|
||||
public function compile(Twig_Compiler $compiler)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ class Twig_Node_If extends Twig_Node
|
|||
/**
|
||||
* Compiles the node to PHP.
|
||||
*
|
||||
* @param Twig_Compiler A Twig_Compiler instance
|
||||
* @param Twig_Compiler $compiler A Twig_Compiler instance
|
||||
*/
|
||||
public function compile(Twig_Compiler $compiler)
|
||||
{
|
||||
|
|
@ -34,7 +34,7 @@ class Twig_Node_If extends Twig_Node
|
|||
if ($i > 0) {
|
||||
$compiler
|
||||
->outdent()
|
||||
->write("} elseif (")
|
||||
->write('} elseif (')
|
||||
;
|
||||
} else {
|
||||
$compiler
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ class Twig_Node_Import extends Twig_Node
|
|||
/**
|
||||
* Compiles the node to PHP.
|
||||
*
|
||||
* @param Twig_Compiler A Twig_Compiler instance
|
||||
* @param Twig_Compiler $compiler A Twig_Compiler instance
|
||||
*/
|
||||
public function compile(Twig_Compiler $compiler)
|
||||
{
|
||||
|
|
@ -36,12 +36,16 @@ class Twig_Node_Import extends Twig_Node
|
|||
;
|
||||
|
||||
if ($this->getNode('expr') instanceof Twig_Node_Expression_Name && '_self' === $this->getNode('expr')->getAttribute('name')) {
|
||||
$compiler->raw("\$this");
|
||||
$compiler->raw('$this');
|
||||
} else {
|
||||
$compiler
|
||||
->raw('$this->env->loadTemplate(')
|
||||
->raw('$this->loadTemplate(')
|
||||
->subcompile($this->getNode('expr'))
|
||||
->raw(")")
|
||||
->raw(', ')
|
||||
->repr($compiler->getFilename())
|
||||
->raw(', ')
|
||||
->repr($this->getLine())
|
||||
->raw(')')
|
||||
;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,13 +19,13 @@ class Twig_Node_Include extends Twig_Node implements Twig_NodeOutputInterface
|
|||
{
|
||||
public function __construct(Twig_Node_Expression $expr, Twig_Node_Expression $variables = null, $only = false, $ignoreMissing = false, $lineno, $tag = null)
|
||||
{
|
||||
parent::__construct(array('expr' => $expr, 'variables' => $variables), array('only' => (Boolean) $only, 'ignore_missing' => (Boolean) $ignoreMissing), $lineno, $tag);
|
||||
parent::__construct(array('expr' => $expr, 'variables' => $variables), array('only' => (bool) $only, 'ignore_missing' => (bool) $ignoreMissing), $lineno, $tag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compiles the node to PHP.
|
||||
*
|
||||
* @param Twig_Compiler A Twig_Compiler instance
|
||||
* @param Twig_Compiler $compiler A Twig_Compiler instance
|
||||
*/
|
||||
public function compile(Twig_Compiler $compiler)
|
||||
{
|
||||
|
|
@ -60,40 +60,29 @@ class Twig_Node_Include extends Twig_Node implements Twig_NodeOutputInterface
|
|||
|
||||
protected function addGetTemplate(Twig_Compiler $compiler)
|
||||
{
|
||||
if ($this->getNode('expr') instanceof Twig_Node_Expression_Constant) {
|
||||
$compiler
|
||||
->write("\$this->env->loadTemplate(")
|
||||
->subcompile($this->getNode('expr'))
|
||||
->raw(")")
|
||||
;
|
||||
} else {
|
||||
$compiler
|
||||
->write("\$template = \$this->env->resolveTemplate(")
|
||||
->subcompile($this->getNode('expr'))
|
||||
->raw(");\n")
|
||||
->write('$template')
|
||||
;
|
||||
}
|
||||
$compiler
|
||||
->write('$this->loadTemplate(')
|
||||
->subcompile($this->getNode('expr'))
|
||||
->raw(', ')
|
||||
->repr($compiler->getFilename())
|
||||
->raw(', ')
|
||||
->repr($this->getLine())
|
||||
->raw(')')
|
||||
;
|
||||
}
|
||||
|
||||
protected function addTemplateArguments(Twig_Compiler $compiler)
|
||||
{
|
||||
if (false === $this->getAttribute('only')) {
|
||||
if (null === $this->getNode('variables')) {
|
||||
$compiler->raw('$context');
|
||||
} else {
|
||||
$compiler
|
||||
->raw('array_merge($context, ')
|
||||
->subcompile($this->getNode('variables'))
|
||||
->raw(')')
|
||||
;
|
||||
}
|
||||
if (null === $this->getNode('variables')) {
|
||||
$compiler->raw(false === $this->getAttribute('only') ? '$context' : 'array()');
|
||||
} elseif (false === $this->getAttribute('only')) {
|
||||
$compiler
|
||||
->raw('array_merge($context, ')
|
||||
->subcompile($this->getNode('variables'))
|
||||
->raw(')')
|
||||
;
|
||||
} else {
|
||||
if (null === $this->getNode('variables')) {
|
||||
$compiler->raw('array()');
|
||||
} else {
|
||||
$compiler->subcompile($this->getNode('variables'));
|
||||
}
|
||||
$compiler->subcompile($this->getNode('variables'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,28 +16,36 @@
|
|||
*/
|
||||
class Twig_Node_Macro extends Twig_Node
|
||||
{
|
||||
const VARARGS_NAME = 'varargs';
|
||||
|
||||
public function __construct($name, Twig_NodeInterface $body, Twig_NodeInterface $arguments, $lineno, $tag = null)
|
||||
{
|
||||
foreach ($arguments as $argumentName => $argument) {
|
||||
if (self::VARARGS_NAME === $argumentName) {
|
||||
throw new Twig_Error_Syntax(sprintf('The argument "%s" in macro "%s" cannot be defined because the variable "%s" is reserved for arbitrary arguments', self::VARARGS_NAME, $name, self::VARARGS_NAME), $argument->getLine());
|
||||
}
|
||||
}
|
||||
|
||||
parent::__construct(array('body' => $body, 'arguments' => $arguments), array('name' => $name), $lineno, $tag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compiles the node to PHP.
|
||||
*
|
||||
* @param Twig_Compiler A Twig_Compiler instance
|
||||
* @param Twig_Compiler $compiler A Twig_Compiler instance
|
||||
*/
|
||||
public function compile(Twig_Compiler $compiler)
|
||||
{
|
||||
$compiler
|
||||
->addDebugInfo($this)
|
||||
->write(sprintf("public function get%s(", $this->getAttribute('name')))
|
||||
->write(sprintf('public function get%s(', $this->getAttribute('name')))
|
||||
;
|
||||
|
||||
$count = count($this->getNode('arguments'));
|
||||
$pos = 0;
|
||||
foreach ($this->getNode('arguments') as $name => $default) {
|
||||
$compiler
|
||||
->raw('$_'.$name.' = ')
|
||||
->raw('$__'.$name.'__ = ')
|
||||
->subcompile($default)
|
||||
;
|
||||
|
||||
|
|
@ -46,36 +54,55 @@ class Twig_Node_Macro extends Twig_Node
|
|||
}
|
||||
}
|
||||
|
||||
if (PHP_VERSION_ID >= 50600) {
|
||||
if ($count) {
|
||||
$compiler->raw(', ');
|
||||
}
|
||||
|
||||
$compiler->raw('...$__varargs__');
|
||||
}
|
||||
|
||||
$compiler
|
||||
->raw(")\n")
|
||||
->write("{\n")
|
||||
->indent()
|
||||
;
|
||||
|
||||
if (!count($this->getNode('arguments'))) {
|
||||
$compiler->write("\$context = \$this->env->getGlobals();\n\n");
|
||||
} else {
|
||||
$compiler
|
||||
->write("\$context = \$this->env->mergeGlobals(array(\n")
|
||||
->indent()
|
||||
;
|
||||
|
||||
foreach ($this->getNode('arguments') as $name => $default) {
|
||||
$compiler
|
||||
->write('')
|
||||
->string($name)
|
||||
->raw(' => $_'.$name)
|
||||
->raw(",\n")
|
||||
;
|
||||
}
|
||||
$compiler
|
||||
->write("\$context = \$this->env->mergeGlobals(array(\n")
|
||||
->indent()
|
||||
;
|
||||
|
||||
foreach ($this->getNode('arguments') as $name => $default) {
|
||||
$compiler
|
||||
->outdent()
|
||||
->write("));\n\n")
|
||||
->addIndentation()
|
||||
->string($name)
|
||||
->raw(' => $__'.$name.'__')
|
||||
->raw(",\n")
|
||||
;
|
||||
}
|
||||
|
||||
$compiler
|
||||
->addIndentation()
|
||||
->string(self::VARARGS_NAME)
|
||||
->raw(' => ')
|
||||
;
|
||||
|
||||
if (PHP_VERSION_ID >= 50600) {
|
||||
$compiler->raw("\$__varargs__,\n");
|
||||
} else {
|
||||
$compiler
|
||||
->raw('func_num_args() > ')
|
||||
->repr($count)
|
||||
->raw(' ? array_slice(func_get_args(), ')
|
||||
->repr($count)
|
||||
->raw(") : array(),\n")
|
||||
;
|
||||
}
|
||||
|
||||
$compiler
|
||||
->outdent()
|
||||
->write("));\n\n")
|
||||
->write("\$blocks = array();\n\n")
|
||||
->write("ob_start();\n")
|
||||
->write("try {\n")
|
||||
|
|
|
|||
|
|
@ -13,6 +13,10 @@
|
|||
/**
|
||||
* Represents a module node.
|
||||
*
|
||||
* Consider this class as being final. If you need to customize the behavior of
|
||||
* the generated class, consider adding nodes to the following nodes: display_start,
|
||||
* display_end, constructor_start, constructor_end, and class_end.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class Twig_Node_Module extends Twig_Node
|
||||
|
|
@ -20,7 +24,22 @@ class Twig_Node_Module extends Twig_Node
|
|||
public function __construct(Twig_NodeInterface $body, Twig_Node_Expression $parent = null, Twig_NodeInterface $blocks, Twig_NodeInterface $macros, Twig_NodeInterface $traits, $embeddedTemplates, $filename)
|
||||
{
|
||||
// embedded templates are set as attributes so that they are only visited once by the visitors
|
||||
parent::__construct(array('parent' => $parent, 'body' => $body, 'blocks' => $blocks, 'macros' => $macros, 'traits' => $traits), array('filename' => $filename, 'index' => null, 'embedded_templates' => $embeddedTemplates), 1);
|
||||
parent::__construct(array(
|
||||
'parent' => $parent,
|
||||
'body' => $body,
|
||||
'blocks' => $blocks,
|
||||
'macros' => $macros,
|
||||
'traits' => $traits,
|
||||
'display_start' => new Twig_Node(),
|
||||
'display_end' => new Twig_Node(),
|
||||
'constructor_start' => new Twig_Node(),
|
||||
'constructor_end' => new Twig_Node(),
|
||||
'class_end' => new Twig_Node(),
|
||||
), array(
|
||||
'filename' => $filename,
|
||||
'index' => null,
|
||||
'embedded_templates' => $embeddedTemplates,
|
||||
), 1);
|
||||
}
|
||||
|
||||
public function setIndex($index)
|
||||
|
|
@ -31,7 +50,7 @@ class Twig_Node_Module extends Twig_Node
|
|||
/**
|
||||
* Compiles the node to PHP.
|
||||
*
|
||||
* @param Twig_Compiler A Twig_Compiler instance
|
||||
* @param Twig_Compiler $compiler A Twig_Compiler instance
|
||||
*/
|
||||
public function compile(Twig_Compiler $compiler)
|
||||
{
|
||||
|
|
@ -50,17 +69,20 @@ class Twig_Node_Module extends Twig_Node
|
|||
|
||||
$this->compileClassHeader($compiler);
|
||||
|
||||
if (count($this->getNode('blocks')) || count($this->getNode('traits')) || null === $this->getNode('parent') || $this->getNode('parent') instanceof Twig_Node_Expression_Constant) {
|
||||
if (
|
||||
count($this->getNode('blocks'))
|
||||
|| count($this->getNode('traits'))
|
||||
|| null === $this->getNode('parent')
|
||||
|| $this->getNode('parent') instanceof Twig_Node_Expression_Constant
|
||||
|| count($this->getNode('constructor_start'))
|
||||
|| count($this->getNode('constructor_end'))
|
||||
) {
|
||||
$this->compileConstructor($compiler);
|
||||
}
|
||||
|
||||
$this->compileGetParent($compiler);
|
||||
|
||||
$this->compileDisplayHeader($compiler);
|
||||
|
||||
$this->compileDisplayBody($compiler);
|
||||
|
||||
$this->compileDisplayFooter($compiler);
|
||||
$this->compileDisplay($compiler);
|
||||
|
||||
$compiler->subcompile($this->getNode('blocks'));
|
||||
|
||||
|
|
@ -77,23 +99,28 @@ class Twig_Node_Module extends Twig_Node
|
|||
|
||||
protected function compileGetParent(Twig_Compiler $compiler)
|
||||
{
|
||||
if (null === $this->getNode('parent')) {
|
||||
if (null === $parent = $this->getNode('parent')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$compiler
|
||||
->write("protected function doGetParent(array \$context)\n", "{\n")
|
||||
->indent()
|
||||
->write("return ")
|
||||
->addDebugInfo($parent)
|
||||
->write('return ')
|
||||
;
|
||||
|
||||
if ($this->getNode('parent') instanceof Twig_Node_Expression_Constant) {
|
||||
$compiler->subcompile($this->getNode('parent'));
|
||||
if ($parent instanceof Twig_Node_Expression_Constant) {
|
||||
$compiler->subcompile($parent);
|
||||
} else {
|
||||
$compiler
|
||||
->raw("\$this->env->resolveTemplate(")
|
||||
->subcompile($this->getNode('parent'))
|
||||
->raw(")")
|
||||
->raw('$this->loadTemplate(')
|
||||
->subcompile($parent)
|
||||
->raw(', ')
|
||||
->repr($compiler->getFilename())
|
||||
->raw(', ')
|
||||
->repr($this->getNode('parent')->getLine())
|
||||
->raw(')')
|
||||
;
|
||||
}
|
||||
|
||||
|
|
@ -104,26 +131,12 @@ class Twig_Node_Module extends Twig_Node
|
|||
;
|
||||
}
|
||||
|
||||
protected function compileDisplayBody(Twig_Compiler $compiler)
|
||||
{
|
||||
$compiler->subcompile($this->getNode('body'));
|
||||
|
||||
if (null !== $this->getNode('parent')) {
|
||||
if ($this->getNode('parent') instanceof Twig_Node_Expression_Constant) {
|
||||
$compiler->write("\$this->parent");
|
||||
} else {
|
||||
$compiler->write("\$this->getParent(\$context)");
|
||||
}
|
||||
$compiler->raw("->display(\$context, array_merge(\$this->blocks, \$blocks));\n");
|
||||
}
|
||||
}
|
||||
|
||||
protected function compileClassHeader(Twig_Compiler $compiler)
|
||||
{
|
||||
$compiler
|
||||
->write("\n\n")
|
||||
// if the filename contains */, add a blank to avoid a PHP parse error
|
||||
->write("/* ".str_replace('*/', '* /', $this->getAttribute('filename'))." */\n")
|
||||
->write('/* '.str_replace('*/', '* /', $this->getAttribute('filename'))." */\n")
|
||||
->write('class '.$compiler->getEnvironment()->getTemplateClass($this->getAttribute('filename'), $this->getAttribute('index')))
|
||||
->raw(sprintf(" extends %s\n", $compiler->getEnvironment()->getBaseTemplateClass()))
|
||||
->write("{\n")
|
||||
|
|
@ -136,17 +149,23 @@ class Twig_Node_Module extends Twig_Node
|
|||
$compiler
|
||||
->write("public function __construct(Twig_Environment \$env)\n", "{\n")
|
||||
->indent()
|
||||
->subcompile($this->getNode('constructor_start'))
|
||||
->write("parent::__construct(\$env);\n\n")
|
||||
;
|
||||
|
||||
// parent
|
||||
if (null === $this->getNode('parent')) {
|
||||
if (null === $parent = $this->getNode('parent')) {
|
||||
$compiler->write("\$this->parent = false;\n\n");
|
||||
} elseif ($this->getNode('parent') instanceof Twig_Node_Expression_Constant) {
|
||||
} elseif ($parent instanceof Twig_Node_Expression_Constant) {
|
||||
$compiler
|
||||
->write("\$this->parent = \$this->env->loadTemplate(")
|
||||
->subcompile($this->getNode('parent'))
|
||||
->raw(");\n\n")
|
||||
->addDebugInfo($parent)
|
||||
->write('$this->parent = $this->loadTemplate(')
|
||||
->subcompile($parent)
|
||||
->raw(', ')
|
||||
->repr($compiler->getFilename())
|
||||
->raw(', ')
|
||||
->repr($this->getNode('parent')->getLine())
|
||||
->raw(");\n")
|
||||
;
|
||||
}
|
||||
|
||||
|
|
@ -170,23 +189,23 @@ class Twig_Node_Module extends Twig_Node
|
|||
|
||||
foreach ($trait->getNode('targets') as $key => $value) {
|
||||
$compiler
|
||||
->write(sprintf("if (!isset(\$_trait_%s_blocks[", $i))
|
||||
->write(sprintf('if (!isset($_trait_%s_blocks[', $i))
|
||||
->string($key)
|
||||
->raw("])) {\n")
|
||||
->indent()
|
||||
->write("throw new Twig_Error_Runtime(sprintf('Block ")
|
||||
->string($key)
|
||||
->raw(" is not defined in trait ")
|
||||
->raw(' is not defined in trait ')
|
||||
->subcompile($trait->getNode('template'))
|
||||
->raw(".'));\n")
|
||||
->outdent()
|
||||
->write("}\n\n")
|
||||
|
||||
->write(sprintf("\$_trait_%s_blocks[", $i))
|
||||
->write(sprintf('$_trait_%s_blocks[', $i))
|
||||
->subcompile($value)
|
||||
->raw(sprintf("] = \$_trait_%s_blocks[", $i))
|
||||
->raw(sprintf('] = $_trait_%s_blocks[', $i))
|
||||
->string($key)
|
||||
->raw(sprintf("]; unset(\$_trait_%s_blocks[", $i))
|
||||
->raw(sprintf(']; unset($_trait_%s_blocks[', $i))
|
||||
->string($key)
|
||||
->raw("]);\n\n")
|
||||
;
|
||||
|
|
@ -199,9 +218,9 @@ class Twig_Node_Module extends Twig_Node
|
|||
->indent()
|
||||
;
|
||||
|
||||
for ($i = 0; $i < $countTraits; $i++) {
|
||||
for ($i = 0; $i < $countTraits; ++$i) {
|
||||
$compiler
|
||||
->write(sprintf("\$_trait_%s_blocks".($i == $countTraits - 1 ? '' : ',')."\n", $i))
|
||||
->write(sprintf('$_trait_%s_blocks'.($i == $countTraits - 1 ? '' : ',')."\n", $i))
|
||||
;
|
||||
}
|
||||
|
||||
|
|
@ -249,21 +268,32 @@ class Twig_Node_Module extends Twig_Node
|
|||
->outdent()
|
||||
->write(");\n")
|
||||
->outdent()
|
||||
->write("}\n\n");
|
||||
->subcompile($this->getNode('constructor_end'))
|
||||
->write("}\n\n")
|
||||
;
|
||||
}
|
||||
|
||||
protected function compileDisplayHeader(Twig_Compiler $compiler)
|
||||
protected function compileDisplay(Twig_Compiler $compiler)
|
||||
{
|
||||
$compiler
|
||||
->write("protected function doDisplay(array \$context, array \$blocks = array())\n", "{\n")
|
||||
->indent()
|
||||
->subcompile($this->getNode('display_start'))
|
||||
->subcompile($this->getNode('body'))
|
||||
;
|
||||
}
|
||||
|
||||
protected function compileDisplayFooter(Twig_Compiler $compiler)
|
||||
{
|
||||
if (null !== $parent = $this->getNode('parent')) {
|
||||
$compiler->addDebugInfo($parent);
|
||||
if ($parent instanceof Twig_Node_Expression_Constant) {
|
||||
$compiler->write('$this->parent');
|
||||
} else {
|
||||
$compiler->write('$this->getParent($context)');
|
||||
}
|
||||
$compiler->raw("->display(\$context, array_merge(\$this->blocks, \$blocks));\n");
|
||||
}
|
||||
|
||||
$compiler
|
||||
->subcompile($this->getNode('display_end'))
|
||||
->outdent()
|
||||
->write("}\n\n")
|
||||
;
|
||||
|
|
@ -272,6 +302,7 @@ class Twig_Node_Module extends Twig_Node
|
|||
protected function compileClassFooter(Twig_Compiler $compiler)
|
||||
{
|
||||
$compiler
|
||||
->subcompile($this->getNode('class_end'))
|
||||
->outdent()
|
||||
->write("}\n")
|
||||
;
|
||||
|
|
@ -362,22 +393,16 @@ class Twig_Node_Module extends Twig_Node
|
|||
{
|
||||
if ($node instanceof Twig_Node_Expression_Constant) {
|
||||
$compiler
|
||||
->write(sprintf("%s = \$this->env->loadTemplate(", $var))
|
||||
->write(sprintf('%s = $this->loadTemplate(', $var))
|
||||
->subcompile($node)
|
||||
->raw(', ')
|
||||
->repr($compiler->getFilename())
|
||||
->raw(', ')
|
||||
->repr($node->getLine())
|
||||
->raw(");\n")
|
||||
;
|
||||
} else {
|
||||
$compiler
|
||||
->write(sprintf("%s = ", $var))
|
||||
->subcompile($node)
|
||||
->raw(";\n")
|
||||
->write(sprintf("if (!%s", $var))
|
||||
->raw(" instanceof Twig_Template) {\n")
|
||||
->indent()
|
||||
->write(sprintf("%s = \$this->env->loadTemplate(%s);\n", $var, $var))
|
||||
->outdent()
|
||||
->write("}\n")
|
||||
;
|
||||
throw new LogicException('Trait templates can only be constant nodes');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ class Twig_Node_Print extends Twig_Node implements Twig_NodeOutputInterface
|
|||
/**
|
||||
* Compiles the node to PHP.
|
||||
*
|
||||
* @param Twig_Compiler A Twig_Compiler instance
|
||||
* @param Twig_Compiler $compiler A Twig_Compiler instance
|
||||
*/
|
||||
public function compile(Twig_Compiler $compiler)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ class Twig_Node_Sandbox extends Twig_Node
|
|||
/**
|
||||
* Compiles the node to PHP.
|
||||
*
|
||||
* @param Twig_Compiler A Twig_Compiler instance
|
||||
* @param Twig_Compiler $compiler A Twig_Compiler instance
|
||||
*/
|
||||
public function compile(Twig_Compiler $compiler)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,60 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) 2009 Fabien Potencier
|
||||
* (c) 2009 Armin Ronacher
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Represents a module node.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class Twig_Node_SandboxedModule extends Twig_Node_Module
|
||||
{
|
||||
protected $usedFilters;
|
||||
protected $usedTags;
|
||||
protected $usedFunctions;
|
||||
|
||||
public function __construct(Twig_Node_Module $node, array $usedFilters, array $usedTags, array $usedFunctions)
|
||||
{
|
||||
parent::__construct($node->getNode('body'), $node->getNode('parent'), $node->getNode('blocks'), $node->getNode('macros'), $node->getNode('traits'), $node->getAttribute('embedded_templates'), $node->getAttribute('filename'), $node->getLine(), $node->getNodeTag());
|
||||
|
||||
$this->setAttribute('index', $node->getAttribute('index'));
|
||||
|
||||
$this->usedFilters = $usedFilters;
|
||||
$this->usedTags = $usedTags;
|
||||
$this->usedFunctions = $usedFunctions;
|
||||
}
|
||||
|
||||
protected function compileDisplayBody(Twig_Compiler $compiler)
|
||||
{
|
||||
$compiler->write("\$this->checkSecurity();\n");
|
||||
|
||||
parent::compileDisplayBody($compiler);
|
||||
}
|
||||
|
||||
protected function compileDisplayFooter(Twig_Compiler $compiler)
|
||||
{
|
||||
parent::compileDisplayFooter($compiler);
|
||||
|
||||
$compiler
|
||||
->write("protected function checkSecurity()\n", "{\n")
|
||||
->indent()
|
||||
->write("\$this->env->getExtension('sandbox')->checkSecurity(\n")
|
||||
->indent()
|
||||
->write(!$this->usedTags ? "array(),\n" : "array('".implode('\', \'', $this->usedTags)."'),\n")
|
||||
->write(!$this->usedFilters ? "array(),\n" : "array('".implode('\', \'', $this->usedFilters)."'),\n")
|
||||
->write(!$this->usedFunctions ? "array()\n" : "array('".implode('\', \'', $this->usedFunctions)."')\n")
|
||||
->outdent()
|
||||
->write(");\n")
|
||||
->outdent()
|
||||
->write("}\n\n")
|
||||
;
|
||||
}
|
||||
}
|
||||
|
|
@ -29,7 +29,7 @@ class Twig_Node_SandboxedPrint extends Twig_Node_Print
|
|||
/**
|
||||
* Compiles the node to PHP.
|
||||
*
|
||||
* @param Twig_Compiler A Twig_Compiler instance
|
||||
* @param Twig_Compiler $compiler A Twig_Compiler instance
|
||||
*/
|
||||
public function compile(Twig_Compiler $compiler)
|
||||
{
|
||||
|
|
@ -47,6 +47,8 @@ class Twig_Node_SandboxedPrint extends Twig_Node_Print
|
|||
* This is mostly needed when another visitor adds filters (like the escaper one).
|
||||
*
|
||||
* @param Twig_Node $node A Node
|
||||
*
|
||||
* @return Twig_Node
|
||||
*/
|
||||
protected function removeNodeFilter($node)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ class Twig_Node_Set extends Twig_Node
|
|||
/**
|
||||
* Compiles the node to PHP.
|
||||
*
|
||||
* @param Twig_Compiler A Twig_Compiler instance
|
||||
* @param Twig_Compiler $compiler A Twig_Compiler instance
|
||||
*/
|
||||
public function compile(Twig_Compiler $compiler)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ class Twig_Node_Spaceless extends Twig_Node
|
|||
/**
|
||||
* Compiles the node to PHP.
|
||||
*
|
||||
* @param Twig_Compiler A Twig_Compiler instance
|
||||
* @param Twig_Compiler $compiler A Twig_Compiler instance
|
||||
*/
|
||||
public function compile(Twig_Compiler $compiler)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ class Twig_Node_Text extends Twig_Node implements Twig_NodeOutputInterface
|
|||
/**
|
||||
* Compiles the node to PHP.
|
||||
*
|
||||
* @param Twig_Compiler A Twig_Compiler instance
|
||||
* @param Twig_Compiler $compiler A Twig_Compiler instance
|
||||
*/
|
||||
public function compile(Twig_Compiler $compiler)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -13,14 +13,15 @@
|
|||
* Represents a node in the AST.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @deprecated since 1.12 (to be removed in 2.0)
|
||||
*
|
||||
* @deprecated since 1.12 (to be removed in 3.0)
|
||||
*/
|
||||
interface Twig_NodeInterface extends Countable, IteratorAggregate
|
||||
{
|
||||
/**
|
||||
* Compiles the node to PHP.
|
||||
*
|
||||
* @param Twig_Compiler A Twig_Compiler instance
|
||||
* @param Twig_Compiler $compiler A Twig_Compiler instance
|
||||
*/
|
||||
public function compile(Twig_Compiler $compiler);
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
class Twig_NodeTraverser
|
||||
{
|
||||
protected $env;
|
||||
protected $visitors;
|
||||
protected $visitors = array();
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
|
|
@ -30,7 +30,6 @@ class Twig_NodeTraverser
|
|||
public function __construct(Twig_Environment $env, array $visitors = array())
|
||||
{
|
||||
$this->env = $env;
|
||||
$this->visitors = array();
|
||||
foreach ($visitors as $visitor) {
|
||||
$this->addVisitor($visitor);
|
||||
}
|
||||
|
|
@ -54,6 +53,8 @@ class Twig_NodeTraverser
|
|||
* Traverses a node and calls the registered visitors.
|
||||
*
|
||||
* @param Twig_NodeInterface $node A Twig_NodeInterface instance
|
||||
*
|
||||
* @return Twig_NodeInterface
|
||||
*/
|
||||
public function traverse(Twig_NodeInterface $node)
|
||||
{
|
||||
|
|
@ -70,7 +71,7 @@ class Twig_NodeTraverser
|
|||
protected function traverseForVisitor(Twig_NodeVisitorInterface $visitor, Twig_NodeInterface $node = null)
|
||||
{
|
||||
if (null === $node) {
|
||||
return null;
|
||||
return;
|
||||
}
|
||||
|
||||
$node = $visitor->enterNode($node, $this->env);
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class Twig_NodeVisitor_Escaper implements Twig_NodeVisitorInterface
|
||||
class Twig_NodeVisitor_Escaper extends Twig_BaseNodeVisitor
|
||||
{
|
||||
protected $statusStack = array();
|
||||
protected $blocks = array();
|
||||
|
|
@ -29,14 +29,9 @@ class Twig_NodeVisitor_Escaper implements Twig_NodeVisitorInterface
|
|||
}
|
||||
|
||||
/**
|
||||
* Called before child nodes are visited.
|
||||
*
|
||||
* @param Twig_NodeInterface $node The node to visit
|
||||
* @param Twig_Environment $env The Twig environment instance
|
||||
*
|
||||
* @return Twig_NodeInterface The modified node
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function enterNode(Twig_NodeInterface $node, Twig_Environment $env)
|
||||
protected function doEnterNode(Twig_Node $node, Twig_Environment $env)
|
||||
{
|
||||
if ($node instanceof Twig_Node_Module) {
|
||||
if ($env->hasExtension('escaper') && $defaultStrategy = $env->getExtension('escaper')->getDefaultStrategy($node->getAttribute('filename'))) {
|
||||
|
|
@ -55,14 +50,9 @@ class Twig_NodeVisitor_Escaper implements Twig_NodeVisitorInterface
|
|||
}
|
||||
|
||||
/**
|
||||
* Called after child nodes are visited.
|
||||
*
|
||||
* @param Twig_NodeInterface $node The node to visit
|
||||
* @param Twig_Environment $env The Twig environment instance
|
||||
*
|
||||
* @return Twig_NodeInterface The modified node
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function leaveNode(Twig_NodeInterface $node, Twig_Environment $env)
|
||||
protected function doLeaveNode(Twig_Node $node, Twig_Environment $env)
|
||||
{
|
||||
if ($node instanceof Twig_Node_Module) {
|
||||
$this->defaultStrategy = false;
|
||||
|
|
|
|||
|
|
@ -19,15 +19,16 @@
|
|||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class Twig_NodeVisitor_Optimizer implements Twig_NodeVisitorInterface
|
||||
class Twig_NodeVisitor_Optimizer extends Twig_BaseNodeVisitor
|
||||
{
|
||||
const OPTIMIZE_ALL = -1;
|
||||
const OPTIMIZE_NONE = 0;
|
||||
const OPTIMIZE_FOR = 2;
|
||||
const OPTIMIZE_RAW_FILTER = 4;
|
||||
const OPTIMIZE_VAR_ACCESS = 8;
|
||||
const OPTIMIZE_ALL = -1;
|
||||
const OPTIMIZE_NONE = 0;
|
||||
const OPTIMIZE_FOR = 2;
|
||||
const OPTIMIZE_RAW_FILTER = 4;
|
||||
const OPTIMIZE_VAR_ACCESS = 8;
|
||||
|
||||
protected $loops = array();
|
||||
protected $loopsTargets = array();
|
||||
protected $optimizers;
|
||||
protected $prependedNodes = array();
|
||||
protected $inABody = false;
|
||||
|
|
@ -35,7 +36,7 @@ class Twig_NodeVisitor_Optimizer implements Twig_NodeVisitorInterface
|
|||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param integer $optimizers The optimizer mode
|
||||
* @param int $optimizers The optimizer mode
|
||||
*/
|
||||
public function __construct($optimizers = -1)
|
||||
{
|
||||
|
|
@ -49,13 +50,13 @@ class Twig_NodeVisitor_Optimizer implements Twig_NodeVisitorInterface
|
|||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function enterNode(Twig_NodeInterface $node, Twig_Environment $env)
|
||||
protected function doEnterNode(Twig_Node $node, Twig_Environment $env)
|
||||
{
|
||||
if (self::OPTIMIZE_FOR === (self::OPTIMIZE_FOR & $this->optimizers)) {
|
||||
$this->enterOptimizeFor($node, $env);
|
||||
}
|
||||
|
||||
if (!version_compare(phpversion(), '5.4.0RC1', '>=') && self::OPTIMIZE_VAR_ACCESS === (self::OPTIMIZE_VAR_ACCESS & $this->optimizers) && !$env->isStrictVariables() && !$env->hasExtension('sandbox')) {
|
||||
if (PHP_VERSION_ID < 50400 && self::OPTIMIZE_VAR_ACCESS === (self::OPTIMIZE_VAR_ACCESS & $this->optimizers) && !$env->isStrictVariables() && !$env->hasExtension('sandbox')) {
|
||||
if ($this->inABody) {
|
||||
if (!$node instanceof Twig_Node_Expression) {
|
||||
if (get_class($node) !== 'Twig_Node') {
|
||||
|
|
@ -75,7 +76,7 @@ class Twig_NodeVisitor_Optimizer implements Twig_NodeVisitorInterface
|
|||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function leaveNode(Twig_NodeInterface $node, Twig_Environment $env)
|
||||
protected function doLeaveNode(Twig_Node $node, Twig_Environment $env)
|
||||
{
|
||||
$expression = $node instanceof Twig_Node_Expression;
|
||||
|
||||
|
|
@ -128,6 +129,8 @@ class Twig_NodeVisitor_Optimizer implements Twig_NodeVisitorInterface
|
|||
*
|
||||
* @param Twig_NodeInterface $node A Node
|
||||
* @param Twig_Environment $env The current Twig environment
|
||||
*
|
||||
* @return Twig_NodeInterface
|
||||
*/
|
||||
protected function optimizePrintNode(Twig_NodeInterface $node, Twig_Environment $env)
|
||||
{
|
||||
|
|
@ -152,6 +155,8 @@ class Twig_NodeVisitor_Optimizer implements Twig_NodeVisitorInterface
|
|||
*
|
||||
* @param Twig_NodeInterface $node A Node
|
||||
* @param Twig_Environment $env The current Twig environment
|
||||
*
|
||||
* @return Twig_NodeInterface
|
||||
*/
|
||||
protected function optimizeRawFilter(Twig_NodeInterface $node, Twig_Environment $env)
|
||||
{
|
||||
|
|
@ -174,6 +179,8 @@ class Twig_NodeVisitor_Optimizer implements Twig_NodeVisitorInterface
|
|||
// disable the loop variable by default
|
||||
$node->setAttribute('with_loop', false);
|
||||
array_unshift($this->loops, $node);
|
||||
array_unshift($this->loopsTargets, $node->getNode('value_target')->getAttribute('name'));
|
||||
array_unshift($this->loopsTargets, $node->getNode('key_target')->getAttribute('name'));
|
||||
} elseif (!$this->loops) {
|
||||
// we are outside a loop
|
||||
return;
|
||||
|
|
@ -183,9 +190,15 @@ class Twig_NodeVisitor_Optimizer implements Twig_NodeVisitorInterface
|
|||
|
||||
// the loop variable is referenced for the current loop
|
||||
elseif ($node instanceof Twig_Node_Expression_Name && 'loop' === $node->getAttribute('name')) {
|
||||
$node->setAttribute('always_defined', true);
|
||||
$this->addLoopToCurrent();
|
||||
}
|
||||
|
||||
// optimize access to loop targets
|
||||
elseif ($node instanceof Twig_Node_Expression_Name && in_array($node->getAttribute('name'), $this->loopsTargets)) {
|
||||
$node->setAttribute('always_defined', true);
|
||||
}
|
||||
|
||||
// block reference
|
||||
elseif ($node instanceof Twig_Node_BlockReference || $node instanceof Twig_Node_Expression_BlockReference) {
|
||||
$this->addLoopToCurrent();
|
||||
|
|
@ -196,6 +209,16 @@ class Twig_NodeVisitor_Optimizer implements Twig_NodeVisitorInterface
|
|||
$this->addLoopToAll();
|
||||
}
|
||||
|
||||
// include function without the with_context=false parameter
|
||||
elseif ($node instanceof Twig_Node_Expression_Function
|
||||
&& 'include' === $node->getAttribute('name')
|
||||
&& (!$node->getNode('arguments')->hasNode('with_context')
|
||||
|| false !== $node->getNode('arguments')->getNode('with_context')->getAttribute('value')
|
||||
)
|
||||
) {
|
||||
$this->addLoopToAll();
|
||||
}
|
||||
|
||||
// the loop variable is referenced via an attribute
|
||||
elseif ($node instanceof Twig_Node_Expression_GetAttr
|
||||
&& (!$node->getNode('attribute') instanceof Twig_Node_Expression_Constant
|
||||
|
|
@ -221,6 +244,8 @@ class Twig_NodeVisitor_Optimizer implements Twig_NodeVisitorInterface
|
|||
{
|
||||
if ($node instanceof Twig_Node_For) {
|
||||
array_shift($this->loops);
|
||||
array_shift($this->loopsTargets);
|
||||
array_shift($this->loopsTargets);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,15 @@
|
|||
<?php
|
||||
|
||||
class Twig_NodeVisitor_SafeAnalysis implements Twig_NodeVisitorInterface
|
||||
/*
|
||||
* This file is part of Twig.
|
||||
*
|
||||
* (c) Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
class Twig_NodeVisitor_SafeAnalysis extends Twig_BaseNodeVisitor
|
||||
{
|
||||
protected $data = array();
|
||||
protected $safeVars = array();
|
||||
|
|
@ -48,12 +57,18 @@ class Twig_NodeVisitor_SafeAnalysis implements Twig_NodeVisitorInterface
|
|||
);
|
||||
}
|
||||
|
||||
public function enterNode(Twig_NodeInterface $node, Twig_Environment $env)
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function doEnterNode(Twig_Node $node, Twig_Environment $env)
|
||||
{
|
||||
return $node;
|
||||
}
|
||||
|
||||
public function leaveNode(Twig_NodeInterface $node, Twig_Environment $env)
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function doLeaveNode(Twig_Node $node, Twig_Environment $env)
|
||||
{
|
||||
if ($node instanceof Twig_Node_Expression_Constant) {
|
||||
// constants are marked safe for all
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class Twig_NodeVisitor_Sandbox implements Twig_NodeVisitorInterface
|
||||
class Twig_NodeVisitor_Sandbox extends Twig_BaseNodeVisitor
|
||||
{
|
||||
protected $inAModule = false;
|
||||
protected $tags;
|
||||
|
|
@ -22,14 +22,9 @@ class Twig_NodeVisitor_Sandbox implements Twig_NodeVisitorInterface
|
|||
protected $functions;
|
||||
|
||||
/**
|
||||
* Called before child nodes are visited.
|
||||
*
|
||||
* @param Twig_NodeInterface $node The node to visit
|
||||
* @param Twig_Environment $env The Twig environment instance
|
||||
*
|
||||
* @return Twig_NodeInterface The modified node
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function enterNode(Twig_NodeInterface $node, Twig_Environment $env)
|
||||
protected function doEnterNode(Twig_Node $node, Twig_Environment $env)
|
||||
{
|
||||
if ($node instanceof Twig_Node_Module) {
|
||||
$this->inAModule = true;
|
||||
|
|
@ -40,18 +35,18 @@ class Twig_NodeVisitor_Sandbox implements Twig_NodeVisitorInterface
|
|||
return $node;
|
||||
} elseif ($this->inAModule) {
|
||||
// look for tags
|
||||
if ($node->getNodeTag()) {
|
||||
$this->tags[] = $node->getNodeTag();
|
||||
if ($node->getNodeTag() && !isset($this->tags[$node->getNodeTag()])) {
|
||||
$this->tags[$node->getNodeTag()] = $node;
|
||||
}
|
||||
|
||||
// look for filters
|
||||
if ($node instanceof Twig_Node_Expression_Filter) {
|
||||
$this->filters[] = $node->getNode('filter')->getAttribute('value');
|
||||
if ($node instanceof Twig_Node_Expression_Filter && !isset($this->filters[$node->getNode('filter')->getAttribute('value')])) {
|
||||
$this->filters[$node->getNode('filter')->getAttribute('value')] = $node;
|
||||
}
|
||||
|
||||
// look for functions
|
||||
if ($node instanceof Twig_Node_Expression_Function) {
|
||||
$this->functions[] = $node->getAttribute('name');
|
||||
if ($node instanceof Twig_Node_Expression_Function && !isset($this->functions[$node->getAttribute('name')])) {
|
||||
$this->functions[$node->getAttribute('name')] = $node;
|
||||
}
|
||||
|
||||
// wrap print to check __toString() calls
|
||||
|
|
@ -64,19 +59,14 @@ class Twig_NodeVisitor_Sandbox implements Twig_NodeVisitorInterface
|
|||
}
|
||||
|
||||
/**
|
||||
* Called after child nodes are visited.
|
||||
*
|
||||
* @param Twig_NodeInterface $node The node to visit
|
||||
* @param Twig_Environment $env The Twig environment instance
|
||||
*
|
||||
* @return Twig_NodeInterface The modified node
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function leaveNode(Twig_NodeInterface $node, Twig_Environment $env)
|
||||
protected function doLeaveNode(Twig_Node $node, Twig_Environment $env)
|
||||
{
|
||||
if ($node instanceof Twig_Node_Module) {
|
||||
$this->inAModule = false;
|
||||
|
||||
return new Twig_Node_SandboxedModule($node, array_unique($this->filters), array_unique($this->tags), array_unique($this->functions));
|
||||
$node->setNode('display_start', new Twig_Node(array(new Twig_Node_CheckSecurity($this->filters, $this->tags, $this->functions), $node->getNode('display_start'))));
|
||||
}
|
||||
|
||||
return $node;
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ interface Twig_NodeVisitorInterface
|
|||
*
|
||||
* Priority should be between -10 and 10 (0 is the default).
|
||||
*
|
||||
* @return integer The priority level
|
||||
* @return int The priority level
|
||||
*/
|
||||
public function getPriority();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ class Twig_Parser implements Twig_ParserInterface
|
|||
{
|
||||
// push all variables into the stack to keep the current state of the parser
|
||||
$vars = get_object_vars($this);
|
||||
unset($vars['stack'], $vars['env'], $vars['handlers'], $vars['visitors'], $vars['expressionParser']);
|
||||
unset($vars['stack'], $vars['env'], $vars['handlers'], $vars['visitors'], $vars['expressionParser'], $vars['reservedMacroNames']);
|
||||
$this->stack[] = $vars;
|
||||
|
||||
// tag handlers
|
||||
|
|
@ -254,21 +254,30 @@ class Twig_Parser implements Twig_ParserInterface
|
|||
|
||||
public function setMacro($name, Twig_Node_Macro $node)
|
||||
{
|
||||
if (null === $this->reservedMacroNames) {
|
||||
$this->reservedMacroNames = array();
|
||||
$r = new ReflectionClass($this->env->getBaseTemplateClass());
|
||||
foreach ($r->getMethods() as $method) {
|
||||
$this->reservedMacroNames[] = $method->getName();
|
||||
}
|
||||
}
|
||||
|
||||
if (in_array($name, $this->reservedMacroNames)) {
|
||||
if ($this->isReservedMacroName($name)) {
|
||||
throw new Twig_Error_Syntax(sprintf('"%s" cannot be used as a macro name as it is a reserved keyword', $name), $node->getLine(), $this->getFilename());
|
||||
}
|
||||
|
||||
$this->macros[$name] = $node;
|
||||
}
|
||||
|
||||
public function isReservedMacroName($name)
|
||||
{
|
||||
if (null === $this->reservedMacroNames) {
|
||||
$this->reservedMacroNames = array();
|
||||
$r = new ReflectionClass($this->env->getBaseTemplateClass());
|
||||
foreach ($r->getMethods() as $method) {
|
||||
$methodName = strtolower($method->getName());
|
||||
|
||||
if ('get' === substr($methodName, 0, 3) && isset($methodName[3])) {
|
||||
$this->reservedMacroNames[] = substr($methodName, 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return in_array(strtolower($name), $this->reservedMacroNames);
|
||||
}
|
||||
|
||||
public function addTrait($trait)
|
||||
{
|
||||
$this->traits[] = $trait;
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue