mirror of
https://github.com/twigphp/Twig.git
synced 2026-09-16 04:16:28 +00:00
Merge branch '1.x' into 2.x
* 1.x: updated CHANGELOG bumped version to 1.28 added testing PHP 7.1 Enhance perf of Template::getAttribute() added a note about the default escaping strategy removed Xdebug on Travis
This commit is contained in:
+6
-1
@@ -11,12 +11,16 @@ php:
|
||||
- 5.5
|
||||
- 5.6
|
||||
- 7.0
|
||||
- 7.1
|
||||
- hhvm
|
||||
|
||||
env:
|
||||
- TWIG_EXT=no
|
||||
- TWIG_EXT=yes
|
||||
|
||||
before_install:
|
||||
- if [[ ! $TRAVIS_PHP_VERSION = hhvm* ]]; then phpenv config-rm xdebug.ini || echo "xdebug not available"; fi
|
||||
|
||||
install:
|
||||
- travis_retry composer install
|
||||
|
||||
@@ -29,6 +33,7 @@ matrix:
|
||||
exclude:
|
||||
- php: hhvm
|
||||
env: TWIG_EXT=yes
|
||||
allow_failures:
|
||||
- php: 7.0
|
||||
env: TWIG_EXT=yes
|
||||
- php: 7.1
|
||||
env: TWIG_EXT=yes
|
||||
|
||||
@@ -17,9 +17,9 @@
|
||||
* improved the performance of the filesystem loader
|
||||
* removed features that were deprecated in 1.x
|
||||
|
||||
* 1.27.1 (2016-XX-XX)
|
||||
* 1.28.0 (2016-XX-XX)
|
||||
|
||||
* n/a
|
||||
* optimized the way attributes are fetched
|
||||
|
||||
* 1.27.0 (2016-10-25)
|
||||
|
||||
|
||||
+2
-4
@@ -422,10 +422,8 @@ everything by default.
|
||||
|
||||
Twig supports both, automatic escaping is enabled by default.
|
||||
|
||||
.. note::
|
||||
|
||||
Automatic escaping is only supported if the *escaper* extension has been
|
||||
enabled (which is the default).
|
||||
The automatic escaping strategy can be configured via the
|
||||
:ref:`autoescape<environment_options>` option and defaults to ``html``.
|
||||
|
||||
Working with Manual Escaping
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
+54
-20
@@ -10,6 +10,10 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
if (PHP_VERSION_ID >= 50600) {
|
||||
require_once __DIR__.'/twig_call_method.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* Default base class for compiled templates.
|
||||
*
|
||||
@@ -21,6 +25,9 @@ abstract class Twig_Template
|
||||
const ARRAY_CALL = 'array';
|
||||
const METHOD_CALL = 'method';
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
protected static $cache = array();
|
||||
|
||||
protected $parent;
|
||||
@@ -425,6 +432,8 @@ abstract class Twig_Template
|
||||
* @return mixed The attribute value, or a Boolean when $isDefinedTest is true, or null when the attribute is not set and $ignoreStrictCheck is true
|
||||
*
|
||||
* @throws Twig_Error_Runtime if the attribute does not exist and Twig is running in strict mode and $isDefinedTest is false
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
protected function getAttribute($object, $item, array $arguments = array(), $type = self::ANY_CALL, $isDefinedTest = false, $ignoreStrictCheck = false)
|
||||
{
|
||||
@@ -432,7 +441,7 @@ abstract class Twig_Template
|
||||
if (self::METHOD_CALL !== $type) {
|
||||
$arrayItem = is_bool($item) || is_float($item) ? (int) $item : $item;
|
||||
|
||||
if ((is_array($object) && array_key_exists($arrayItem, $object))
|
||||
if ((is_array($object) && (isset($object[$arrayItem]) || array_key_exists($arrayItem, $object)))
|
||||
|| ($object instanceof ArrayAccess && isset($object[$arrayItem]))
|
||||
) {
|
||||
if ($isDefinedTest) {
|
||||
@@ -513,34 +522,53 @@ abstract class Twig_Template
|
||||
$class = get_class($object);
|
||||
|
||||
// object method
|
||||
if (!isset(self::$cache[$class]['methods'])) {
|
||||
if (!isset(self::$cache[$class])) {
|
||||
// get_class_methods returns all methods accessible in the scope, but we only want public ones to be accessible in templates
|
||||
if ($object instanceof self) {
|
||||
$ref = new ReflectionClass($class);
|
||||
$methods = array();
|
||||
|
||||
foreach ($ref->getMethods(ReflectionMethod::IS_PUBLIC) as $refMethod) {
|
||||
$methods[strtolower($refMethod->name)] = true;
|
||||
$methods[] = $refMethod->name;
|
||||
}
|
||||
} else {
|
||||
$methods = get_class_methods($object);
|
||||
}
|
||||
$cache = array();
|
||||
|
||||
foreach ($methods as $method) {
|
||||
$cache[$method] = $method;
|
||||
$cache[$lcName = strtolower($method)] = $method;
|
||||
|
||||
if ('g' === $lcName[0] && 0 === strpos($lcName, 'get')) {
|
||||
$name = substr($method, 3);
|
||||
$lcName = substr($lcName, 3);
|
||||
} elseif ('i' === $lcName[0] && 0 === strpos($lcName, 'is')) {
|
||||
$name = substr($method, 2);
|
||||
$lcName = substr($lcName, 2);
|
||||
} elseif ('h' === $lcName[0] && 0 === strpos($lcName, 'has')) {
|
||||
$name = substr($method, 3);
|
||||
$lcName = substr($lcName, 3);
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
self::$cache[$class]['methods'] = $methods;
|
||||
} else {
|
||||
self::$cache[$class]['methods'] = array_change_key_case(array_flip(get_class_methods($object)));
|
||||
if (!isset($cache[$name])) {
|
||||
$cache[$name] = $method;
|
||||
}
|
||||
if (!isset($cache[$lcName])) {
|
||||
$cache[$lcName] = $method;
|
||||
}
|
||||
}
|
||||
self::$cache[$class] = $cache;
|
||||
}
|
||||
|
||||
$call = false;
|
||||
$lcItem = strtolower($item);
|
||||
if (isset(self::$cache[$class]['methods'][$lcItem])) {
|
||||
$method = (string) $item;
|
||||
} elseif (isset(self::$cache[$class]['methods']['get'.$lcItem])) {
|
||||
$method = 'get'.$item;
|
||||
} elseif (isset(self::$cache[$class]['methods']['is'.$lcItem])) {
|
||||
$method = 'is'.$item;
|
||||
} elseif (isset(self::$cache[$class]['methods']['has'.$lcItem])) {
|
||||
$method = 'has'.$item;
|
||||
} elseif (isset(self::$cache[$class]['methods']['__call'])) {
|
||||
$method = (string) $item;
|
||||
if (isset(self::$cache[$class][$item])) {
|
||||
$method = self::$cache[$class][$item];
|
||||
} elseif (isset(self::$cache[$class][$lcItem = strtolower($item)])) {
|
||||
$method = self::$cache[$class][$lcItem];
|
||||
} elseif (isset(self::$cache[$class]['__call'])) {
|
||||
$method = $item;
|
||||
$call = true;
|
||||
} else {
|
||||
if ($isDefinedTest) {
|
||||
@@ -551,7 +579,7 @@ abstract class Twig_Template
|
||||
return;
|
||||
}
|
||||
|
||||
throw new Twig_Error_Runtime(sprintf('Neither the property "%1$s" nor one of the methods "%1$s()", "get%1$s()"/"is%1$s()" or "__call()" exist and have public access in class "%2$s".', $item, get_class($object)), -1, $this->getTemplateName());
|
||||
throw new Twig_Error_Runtime(sprintf('Neither the property "%1$s" nor one of the methods "%1$s()", "get%1$s()"/"is%1$s()" or "__call()" exist and have public access in class "%2$s".', $item, $class), -1, $this->getTemplateName());
|
||||
}
|
||||
|
||||
if ($isDefinedTest) {
|
||||
@@ -565,7 +593,13 @@ abstract class Twig_Template
|
||||
// Some objects throw exceptions when they have __call, and the method we try
|
||||
// to call is not supported. If ignoreStrictCheck is true, we should return null.
|
||||
try {
|
||||
$ret = call_user_func_array(array($object, $method), $arguments);
|
||||
if (!$arguments) {
|
||||
$ret = $object->$method();
|
||||
} elseif (PHP_VERSION_ID >= 50600) {
|
||||
$ret = twig_call_method($object, $method, $arguments);
|
||||
} else {
|
||||
$ret = call_user_func_array(array($object, $method), $arguments);
|
||||
}
|
||||
} catch (BadMethodCallException $e) {
|
||||
if ($call && ($ignoreStrictCheck || !$this->env->isStrictVariables())) {
|
||||
return;
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
function twig_call_method($object, $method, $arguments)
|
||||
{
|
||||
return $object->$method(...$arguments);
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
--TEST--
|
||||
"date" function
|
||||
--TEMPLATE--
|
||||
{{ date() == date('now') ? 'OK' : 'KO' }}
|
||||
{{ date().format('r') == date('now').format('r') ? 'OK' : 'KO' }}
|
||||
{{ date(date1) == date('2010-10-04 13:45') ? 'OK' : 'KO' }}
|
||||
{{ date(date2) == date('2010-10-04 13:45') ? 'OK' : 'KO' }}
|
||||
{{ date(date3) == date('2010-10-04 13:45') ? 'OK' : 'KO' }}
|
||||
|
||||
Reference in New Issue
Block a user