mirror of
https://github.com/twigphp/Twig.git
synced 2026-09-12 10:26:32 +00:00
moved Twig_Template::getAttribute() to a function
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
* 2.0.0 (2016-XX-XX)
|
||||
|
||||
* moved Twig_Environment::getAttribute() to twig_get_attribute()
|
||||
* removed Twig_Environment::getLexer(), Twig_Environment::getParser(), Twig_Environment::getCompiler()
|
||||
* removed Twig_Compiler::getFilename()
|
||||
* added hasser support in Twig_Template::getAttribute()
|
||||
|
||||
@@ -926,7 +926,6 @@ class Twig_Environment
|
||||
{
|
||||
$this->optionsHash = implode(':', array(
|
||||
$this->extensionSet->getSignature(),
|
||||
(int) function_exists('twig_template_get_attributes'),
|
||||
PHP_MAJOR_VERSION,
|
||||
PHP_MINOR_VERSION,
|
||||
self::VERSION,
|
||||
|
||||
@@ -1337,3 +1337,188 @@ function twig_array_batch($items, $size, $fill = null)
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the attribute value for a given array/object.
|
||||
*
|
||||
* @param mixed $object The object or array from where to get the item
|
||||
* @param mixed $item The item to get from the array or object
|
||||
* @param array $arguments An array of arguments to pass if the item is an object method
|
||||
* @param string $type The type of attribute (@see Twig_Template constants)
|
||||
* @param bool $isDefinedTest Whether this is only a defined check
|
||||
* @param bool $ignoreStrictCheck Whether to ignore the strict attribute check or not
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
function twig_get_attribute(Twig_Environment $env, Twig_Source $source, $object, $item, array $arguments = array(), $type = Twig_Template::ANY_CALL, $isDefinedTest = false, $ignoreStrictCheck = false)
|
||||
{
|
||||
static $cache = array();
|
||||
|
||||
// array
|
||||
if (Twig_Template::METHOD_CALL !== $type) {
|
||||
$arrayItem = is_bool($item) || is_float($item) ? (int) $item : $item;
|
||||
|
||||
if ((is_array($object) && (isset($object[$arrayItem]) || array_key_exists($arrayItem, $object)))
|
||||
|| ($object instanceof ArrayAccess && isset($object[$arrayItem]))
|
||||
) {
|
||||
if ($isDefinedTest) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return $object[$arrayItem];
|
||||
}
|
||||
|
||||
if (Twig_Template::ARRAY_CALL === $type || !is_object($object)) {
|
||||
if ($isDefinedTest) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($ignoreStrictCheck || !$env->isStrictVariables()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($object instanceof ArrayAccess) {
|
||||
$message = sprintf('Key "%s" in object with ArrayAccess of class "%s" does not exist.', $arrayItem, get_class($object));
|
||||
} 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)) {
|
||||
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) {
|
||||
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);
|
||||
}
|
||||
|
||||
throw new Twig_Error_Runtime($message, -1, $source);
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_object($object)) {
|
||||
if ($isDefinedTest) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($ignoreStrictCheck || !$env->isStrictVariables()) {
|
||||
return;
|
||||
}
|
||||
|
||||
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, $source);
|
||||
}
|
||||
|
||||
if ($object instanceof Twig_Template) {
|
||||
throw new Twig_Error_Runtime('Accessing Twig_Template attributes is forbidden.');
|
||||
}
|
||||
|
||||
// object property
|
||||
if (Twig_Template::METHOD_CALL !== $type) {
|
||||
if (isset($object->$item) || array_key_exists((string) $item, $object)) {
|
||||
if ($isDefinedTest) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($env->hasExtension('Twig_Extension_Sandbox')) {
|
||||
$env->getExtension('Twig_Extension_Sandbox')->checkPropertyAllowed($object, $item);
|
||||
}
|
||||
|
||||
return $object->$item;
|
||||
}
|
||||
}
|
||||
|
||||
$class = get_class($object);
|
||||
|
||||
// object method
|
||||
// precedence: getXxx() > isXxx() > hasXxx()
|
||||
if (!isset($cache[$class])) {
|
||||
$methods = get_class_methods($object);
|
||||
sort($methods);
|
||||
$lcMethods = array_map('strtolower', $methods);
|
||||
$cache = array();
|
||||
foreach ($methods as $i => $method) {
|
||||
$cache[$method] = $method;
|
||||
$cache[$lcName = $lcMethods[$i]] = $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);
|
||||
if (in_array('is'.$lcName, $lcMethods)) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isset($cache[$name])) {
|
||||
$cache[$name] = $method;
|
||||
$cache[$lcName] = $method;
|
||||
}
|
||||
}
|
||||
$cache[$class] = $cache;
|
||||
}
|
||||
|
||||
$call = false;
|
||||
if (isset($cache[$class][$item])) {
|
||||
$method = $cache[$class][$item];
|
||||
} elseif (isset($cache[$class][$lcItem = strtolower($item)])) {
|
||||
$method = $cache[$class][$lcItem];
|
||||
} elseif (isset($cache[$class]['__call'])) {
|
||||
$method = $item;
|
||||
$call = true;
|
||||
} else {
|
||||
if ($isDefinedTest) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($ignoreStrictCheck || !$env->isStrictVariables()) {
|
||||
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()"/"has%1$s()" or "__call()" exist and have public access in class "%2$s".', $item, $class), -1, $source);
|
||||
}
|
||||
|
||||
if ($isDefinedTest) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($env->hasExtension('Twig_Extension_Sandbox')) {
|
||||
$env->getExtension('Twig_Extension_Sandbox')->checkMethodAllowed($object, $method);
|
||||
}
|
||||
|
||||
// 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 = $object->$method(...$arguments);
|
||||
} catch (BadMethodCallException $e) {
|
||||
if ($call && ($ignoreStrictCheck || !$env->isStrictVariables())) {
|
||||
return;
|
||||
}
|
||||
throw $e;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
@@ -23,11 +23,7 @@ class Twig_Node_Expression_GetAttr extends Twig_Node_Expression
|
||||
|
||||
public function compile(Twig_Compiler $compiler)
|
||||
{
|
||||
if (function_exists('twig_template_get_attributes')) {
|
||||
$compiler->raw('twig_template_get_attributes($this, ');
|
||||
} else {
|
||||
$compiler->raw('$this->getAttribute(');
|
||||
}
|
||||
$compiler->raw('twig_get_attribute($this->env, $this->getSourceContext(), ');
|
||||
|
||||
if ($this->getAttribute('ignore_strict_check')) {
|
||||
$this->getNode('node')->setAttribute('ignore_strict_check', true);
|
||||
|
||||
@@ -416,192 +416,4 @@ abstract class Twig_Template
|
||||
* @param array $blocks An array of blocks to pass to the template
|
||||
*/
|
||||
abstract protected function doDisplay(array $context, array $blocks = array());
|
||||
|
||||
/**
|
||||
* Returns the attribute value for a given array/object.
|
||||
*
|
||||
* @param mixed $object The object or array from where to get the item
|
||||
* @param mixed $item The item to get from the array or object
|
||||
* @param array $arguments An array of arguments to pass if the item is an object method
|
||||
* @param string $type The type of attribute (@see Twig_Template constants)
|
||||
* @param bool $isDefinedTest Whether this is only a defined check
|
||||
* @param bool $ignoreStrictCheck Whether to ignore the strict attribute check or not
|
||||
*
|
||||
* @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)
|
||||
{
|
||||
// array
|
||||
if (self::METHOD_CALL !== $type) {
|
||||
$arrayItem = is_bool($item) || is_float($item) ? (int) $item : $item;
|
||||
|
||||
if ((is_array($object) && (isset($object[$arrayItem]) || array_key_exists($arrayItem, $object)))
|
||||
|| ($object instanceof ArrayAccess && isset($object[$arrayItem]))
|
||||
) {
|
||||
if ($isDefinedTest) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return $object[$arrayItem];
|
||||
}
|
||||
|
||||
if (self::ARRAY_CALL === $type || !is_object($object)) {
|
||||
if ($isDefinedTest) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($ignoreStrictCheck || !$this->env->isStrictVariables()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($object instanceof ArrayAccess) {
|
||||
$message = sprintf('Key "%s" in object with ArrayAccess of class "%s" does not exist.', $arrayItem, get_class($object));
|
||||
} 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)) {
|
||||
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 (self::ARRAY_CALL === $type) {
|
||||
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);
|
||||
}
|
||||
|
||||
throw new Twig_Error_Runtime($message, -1, $this->getSourceContext());
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_object($object)) {
|
||||
if ($isDefinedTest) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($ignoreStrictCheck || !$this->env->isStrictVariables()) {
|
||||
return;
|
||||
}
|
||||
|
||||
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->getSourceContext());
|
||||
}
|
||||
|
||||
// object property
|
||||
if (self::METHOD_CALL !== $type && !$object instanceof self) { // Twig_Template does not have public properties, and we don't want to allow access to internal ones
|
||||
if (isset($object->$item) || array_key_exists((string) $item, $object)) {
|
||||
if ($isDefinedTest) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($this->env->hasExtension('Twig_Extension_Sandbox')) {
|
||||
$this->env->getExtension('Twig_Extension_Sandbox')->checkPropertyAllowed($object, $item);
|
||||
}
|
||||
|
||||
return $object->$item;
|
||||
}
|
||||
}
|
||||
|
||||
$class = get_class($object);
|
||||
|
||||
// object method
|
||||
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[] = $refMethod->name;
|
||||
}
|
||||
} else {
|
||||
$methods = get_class_methods($object);
|
||||
}
|
||||
// sort values to have consistent behavior, so that "get" methods win precedence over "is" methods
|
||||
sort($methods);
|
||||
|
||||
$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;
|
||||
}
|
||||
|
||||
if (!isset($cache[$name])) {
|
||||
$cache[$name] = $method;
|
||||
}
|
||||
if (!isset($cache[$lcName])) {
|
||||
$cache[$lcName] = $method;
|
||||
}
|
||||
}
|
||||
self::$cache[$class] = $cache;
|
||||
}
|
||||
|
||||
$call = false;
|
||||
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) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($ignoreStrictCheck || !$this->env->isStrictVariables()) {
|
||||
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, $class), -1, $this->getSourceContext());
|
||||
}
|
||||
|
||||
if ($isDefinedTest) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($this->env->hasExtension('Twig_Extension_Sandbox')) {
|
||||
$this->env->getExtension('Twig_Extension_Sandbox')->checkMethodAllowed($object, $method);
|
||||
}
|
||||
|
||||
// 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 = $object->$method(...$arguments);
|
||||
} catch (BadMethodCallException $e) {
|
||||
if ($call && ($ignoreStrictCheck || !$this->env->isStrictVariables())) {
|
||||
return;
|
||||
}
|
||||
throw $e;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,10 +55,6 @@ abstract class Twig_Test_NodeTestCase extends PHPUnit_Framework_TestCase
|
||||
|
||||
protected function getAttributeGetter()
|
||||
{
|
||||
if (function_exists('twig_template_get_attributes')) {
|
||||
return 'twig_template_get_attributes($this, ';
|
||||
}
|
||||
|
||||
return '$this->getAttribute(';
|
||||
return 'twig_get_attribute($this->env, $this->getSourceContext(), ';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,8 +61,8 @@ class Twig_Tests_TemplateTest extends PHPUnit_Framework_TestCase
|
||||
array('{{ empty_array.a }}', 'Key "a" does not exist as the array is empty in "%s" at line 1.'),
|
||||
array('{{ array.a }}', 'Key "a" for array with keys "foo" does not exist in "%s" at line 1.'),
|
||||
array('{{ attribute(array, -10) }}', 'Key "-10" for array with keys "foo" does not exist in "%s" at line 1.'),
|
||||
array('{{ array_access.a }}', 'Neither the property "a" nor one of the methods "a()", "geta()"/"isa()" or "__call()" exist and have public access in class "Twig_TemplateArrayAccessObject" in "%s" at line 1.'),
|
||||
array('{% from _self import foo %}{% macro foo(obj) %}{{ obj.missing_method() }}{% endmacro %}{{ foo(array_access) }}', 'Neither the property "missing_method" nor one of the methods "missing_method()", "getmissing_method()"/"ismissing_method()" or "__call()" exist and have public access in class "Twig_TemplateArrayAccessObject" in "%s" at line 1.'),
|
||||
array('{{ array_access.a }}', 'Neither the property "a" nor one of the methods "a()", "geta()"/"isa()"/"hasa()" or "__call()" exist and have public access in class "Twig_TemplateArrayAccessObject" in "%s" at line 1.'),
|
||||
array('{% from _self import foo %}{% macro foo(obj) %}{{ obj.missing_method() }}{% endmacro %}{{ foo(array_access) }}', 'Neither the property "missing_method" nor one of the methods "missing_method()", "getmissing_method()"/"ismissing_method()"/"hasmissing_method()" or "__call()" exist and have public access in class "Twig_TemplateArrayAccessObject" in "%s" at line 1.'),
|
||||
array('{{ magic_exception.test }}', 'An exception has been thrown during the rendering of a template ("Hey! Don\'t try to isset me!") in "%s" at line 1.'),
|
||||
array('{{ object["a"] }}', 'Impossible to access a key "a" on an object of class "stdClass" that does not implement ArrayAccess interface in "%s" at line 1.'),
|
||||
);
|
||||
@@ -79,7 +79,7 @@ class Twig_Tests_TemplateTest extends PHPUnit_Framework_TestCase
|
||||
$template = new Twig_TemplateTest($twig);
|
||||
|
||||
try {
|
||||
$template->getAttribute($object, $item, array(), 'any');
|
||||
twig_get_attribute($twig, $template->getSourceContext(), $object, $item, array(), 'any');
|
||||
|
||||
if (!$allowed) {
|
||||
$this->fail();
|
||||
@@ -133,7 +133,8 @@ class Twig_Tests_TemplateTest extends PHPUnit_Framework_TestCase
|
||||
|
||||
public function testGetAttributeOnArrayWithConfusableKey()
|
||||
{
|
||||
$template = new Twig_TemplateTest(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
|
||||
$twig = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock());
|
||||
$template = new Twig_TemplateTest($twig);
|
||||
|
||||
$array = array('Zero', 'One', -1 => 'MinusOne', '' => 'EmptyString', '1.5' => 'FloatButString', '01' => 'IntegerButStringWithLeadingZeros');
|
||||
|
||||
@@ -146,14 +147,14 @@ class Twig_Tests_TemplateTest extends PHPUnit_Framework_TestCase
|
||||
$this->assertSame('IntegerButStringWithLeadingZeros', $array['01']);
|
||||
$this->assertSame('EmptyString', $array[null]);
|
||||
|
||||
$this->assertSame('Zero', $template->getAttribute($array, false), 'false is treated as 0 when accessing an array (equals PHP behavior)');
|
||||
$this->assertSame('One', $template->getAttribute($array, true), 'true is treated as 1 when accessing an array (equals PHP behavior)');
|
||||
$this->assertSame('One', $template->getAttribute($array, 1.5), 'float is casted to int when accessing an array (equals PHP behavior)');
|
||||
$this->assertSame('One', $template->getAttribute($array, '1'), '"1" is treated as integer 1 when accessing an array (equals PHP behavior)');
|
||||
$this->assertSame('MinusOne', $template->getAttribute($array, -1.5), 'negative float is casted to int when accessing an array (equals PHP behavior)');
|
||||
$this->assertSame('FloatButString', $template->getAttribute($array, '1.5'), '"1.5" is treated as-is when accessing an array (equals PHP behavior)');
|
||||
$this->assertSame('IntegerButStringWithLeadingZeros', $template->getAttribute($array, '01'), '"01" is treated as-is when accessing an array (equals PHP behavior)');
|
||||
$this->assertSame('EmptyString', $template->getAttribute($array, null), 'null is treated as "" when accessing an array (equals PHP behavior)');
|
||||
$this->assertSame('Zero', twig_get_attribute($twig, $template->getSourceContext(), $array, false), 'false is treated as 0 when accessing an array (equals PHP behavior)');
|
||||
$this->assertSame('One', twig_get_attribute($twig, $template->getSourceContext(), $array, true), 'true is treated as 1 when accessing an array (equals PHP behavior)');
|
||||
$this->assertSame('One', twig_get_attribute($twig, $template->getSourceContext(), $array, 1.5), 'float is casted to int when accessing an array (equals PHP behavior)');
|
||||
$this->assertSame('One', twig_get_attribute($twig, $template->getSourceContext(), $array, '1'), '"1" is treated as integer 1 when accessing an array (equals PHP behavior)');
|
||||
$this->assertSame('MinusOne', twig_get_attribute($twig, $template->getSourceContext(), $array, -1.5), 'negative float is casted to int when accessing an array (equals PHP behavior)');
|
||||
$this->assertSame('FloatButString', twig_get_attribute($twig, $template->getSourceContext(), $array, '1.5'), '"1.5" is treated as-is when accessing an array (equals PHP behavior)');
|
||||
$this->assertSame('IntegerButStringWithLeadingZeros', twig_get_attribute($twig, $template->getSourceContext(), $array, '01'), '"01" is treated as-is when accessing an array (equals PHP behavior)');
|
||||
$this->assertSame('EmptyString', twig_get_attribute($twig, $template->getSourceContext(), $array, null), 'null is treated as "" when accessing an array (equals PHP behavior)');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -161,9 +162,10 @@ class Twig_Tests_TemplateTest extends PHPUnit_Framework_TestCase
|
||||
*/
|
||||
public function testGetAttribute($defined, $value, $object, $item, $arguments, $type)
|
||||
{
|
||||
$template = new Twig_TemplateTest(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
|
||||
$twig = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock());
|
||||
$template = new Twig_TemplateTest($twig);
|
||||
|
||||
$this->assertEquals($value, $template->getAttribute($object, $item, $arguments, $type));
|
||||
$this->assertEquals($value, twig_get_attribute($twig, $template->getSourceContext(), $object, $item, $arguments, $type));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -171,13 +173,14 @@ class Twig_Tests_TemplateTest extends PHPUnit_Framework_TestCase
|
||||
*/
|
||||
public function testGetAttributeStrict($defined, $value, $object, $item, $arguments, $type, $exceptionMessage = null)
|
||||
{
|
||||
$template = new Twig_TemplateTest(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('strict_variables' => true)));
|
||||
$twig = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('strict_variables' => true));
|
||||
$template = new Twig_TemplateTest($twig);
|
||||
|
||||
if ($defined) {
|
||||
$this->assertEquals($value, $template->getAttribute($object, $item, $arguments, $type));
|
||||
$this->assertEquals($value, twig_get_attribute($twig, $template->getSourceContext(), $object, $item, $arguments, $type));
|
||||
} else {
|
||||
try {
|
||||
$this->assertEquals($value, $template->getAttribute($object, $item, $arguments, $type));
|
||||
$this->assertEquals($value, twig_get_attribute($twig, $template->getSourceContext(), $object, $item, $arguments, $type));
|
||||
|
||||
throw new Exception('Expected Twig_Error_Runtime exception.');
|
||||
} catch (Twig_Error_Runtime $e) {
|
||||
@@ -193,9 +196,10 @@ class Twig_Tests_TemplateTest extends PHPUnit_Framework_TestCase
|
||||
*/
|
||||
public function testGetAttributeDefined($defined, $value, $object, $item, $arguments, $type)
|
||||
{
|
||||
$template = new Twig_TemplateTest(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
|
||||
$twig = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock());
|
||||
$template = new Twig_TemplateTest($twig);
|
||||
|
||||
$this->assertEquals($defined, $template->getAttribute($object, $item, $arguments, $type, true));
|
||||
$this->assertEquals($defined, twig_get_attribute($twig, $template->getSourceContext(), $object, $item, $arguments, $type, true));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -203,18 +207,20 @@ class Twig_Tests_TemplateTest extends PHPUnit_Framework_TestCase
|
||||
*/
|
||||
public function testGetAttributeDefinedStrict($defined, $value, $object, $item, $arguments, $type)
|
||||
{
|
||||
$template = new Twig_TemplateTest(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('strict_variables' => true)));
|
||||
$twig = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('strict_variables' => true));
|
||||
$template = new Twig_TemplateTest($twig);
|
||||
|
||||
$this->assertEquals($defined, $template->getAttribute($object, $item, $arguments, $type, true));
|
||||
$this->assertEquals($defined, twig_get_attribute($twig, $template->getSourceContext(), $object, $item, $arguments, $type, true));
|
||||
}
|
||||
|
||||
public function testGetAttributeCallExceptions()
|
||||
{
|
||||
$template = new Twig_TemplateTest(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()));
|
||||
$twig = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock());
|
||||
$template = new Twig_TemplateTest($twig);
|
||||
|
||||
$object = new Twig_TemplateMagicMethodExceptionObject();
|
||||
|
||||
$this->assertNull($template->getAttribute($object, 'foo'));
|
||||
$this->assertNull(twig_get_attribute($twig, $template->getSourceContext(), $object, 'foo'));
|
||||
}
|
||||
|
||||
public function getGetAttributeTests()
|
||||
@@ -227,6 +233,7 @@ class Twig_Tests_TemplateTest extends PHPUnit_Framework_TestCase
|
||||
'bar' => true,
|
||||
'foo' => true,
|
||||
'baz' => 'baz',
|
||||
'baf' => 'baf',
|
||||
'09' => '09',
|
||||
'+4' => '+4',
|
||||
);
|
||||
@@ -257,6 +264,7 @@ class Twig_Tests_TemplateTest extends PHPUnit_Framework_TestCase
|
||||
array(true, true, 'bar'),
|
||||
array(true, true, 'foo'),
|
||||
array(true, 'baz', 'baz'),
|
||||
array(true, 'baf', 'baf'),
|
||||
array(true, '09', '09'),
|
||||
array(true, '+4', '+4'),
|
||||
);
|
||||
@@ -395,15 +403,6 @@ class Twig_TemplateTest extends Twig_Template
|
||||
{
|
||||
}
|
||||
|
||||
public function getAttribute($object, $item, array $arguments = array(), $type = Twig_Template::ANY_CALL, $isDefinedTest = false, $ignoreStrictCheck = false)
|
||||
{
|
||||
if (function_exists('twig_template_get_attributes')) {
|
||||
return twig_template_get_attributes($this, $object, $item, $arguments, $type, $isDefinedTest, $ignoreStrictCheck);
|
||||
} else {
|
||||
return parent::getAttribute($object, $item, $arguments, $type, $isDefinedTest, $ignoreStrictCheck);
|
||||
}
|
||||
}
|
||||
|
||||
public function block_name($context, array $blocks = array())
|
||||
{
|
||||
}
|
||||
@@ -421,6 +420,7 @@ class Twig_TemplateArrayAccessObject implements ArrayAccess
|
||||
'bar' => true,
|
||||
'foo' => true,
|
||||
'baz' => 'baz',
|
||||
'baf' => 'baf',
|
||||
'09' => '09',
|
||||
'+4' => '+4',
|
||||
);
|
||||
@@ -455,6 +455,7 @@ class Twig_TemplateMagicPropertyObject
|
||||
'bar' => true,
|
||||
'foo' => true,
|
||||
'baz' => 'baz',
|
||||
'baf' => 'baf',
|
||||
'09' => '09',
|
||||
'+4' => '+4',
|
||||
);
|
||||
@@ -488,6 +489,7 @@ class Twig_TemplatePropertyObject
|
||||
public $bar = true;
|
||||
public $foo = true;
|
||||
public $baz = 'baz';
|
||||
public $baf = 'baf';
|
||||
|
||||
protected $protected = 'protected';
|
||||
}
|
||||
@@ -569,9 +571,14 @@ class Twig_TemplateMethodObject
|
||||
return true;
|
||||
}
|
||||
|
||||
public function hasBaz()
|
||||
{
|
||||
return 'should never be returned (has)';
|
||||
}
|
||||
|
||||
public function isBaz()
|
||||
{
|
||||
return 'should never be returned';
|
||||
return 'should never be returned (is)';
|
||||
}
|
||||
|
||||
public function getBaz()
|
||||
@@ -579,6 +586,16 @@ class Twig_TemplateMethodObject
|
||||
return 'baz';
|
||||
}
|
||||
|
||||
public function hasBaf()
|
||||
{
|
||||
return 'should never be returned (has)';
|
||||
}
|
||||
|
||||
public function isBaf()
|
||||
{
|
||||
return 'baf';
|
||||
}
|
||||
|
||||
protected function getProtected()
|
||||
{
|
||||
return 'protected';
|
||||
|
||||
Reference in New Issue
Block a user