Fixed evaluation of short circuit operators

This commit is contained in:
florianv 2014-02-27 03:45:51 +01:00 committed by Fabien Potencier
parent 81e27d2a3e
commit 3a46a8e799
2 changed files with 52 additions and 4 deletions

View File

@ -83,9 +83,10 @@ class BinaryNode extends Node
{
$operator = $this->attributes['operator'];
$left = $this->nodes['left']->evaluate($functions, $values);
$right = $this->nodes['right']->evaluate($functions, $values);
if (isset(self::$functions[$operator])) {
$right = $this->nodes['right']->evaluate($functions, $values);
if ('not in' == $operator) {
return !call_user_func('in_array', $left, $right);
}
@ -96,10 +97,15 @@ class BinaryNode extends Node
switch ($operator) {
case 'or':
case '||':
return $left || $right;
return $left || $this->nodes['right']->evaluate($functions, $values);
case 'and':
case '&&':
return $left && $right;
return $left && $this->nodes['right']->evaluate($functions, $values);
}
$right = $this->nodes['right']->evaluate($functions, $values);
switch ($operator) {
case '|':
return $left | $right;
case '^':

View File

@ -12,7 +12,6 @@
namespace Symfony\Component\ExpressionLanguage\Tests;
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
use Symfony\Component\ExpressionLanguage\ParsedExpression;
class ExpressionLanguageTest extends \PHPUnit_Framework_TestCase
{
@ -54,4 +53,47 @@ class ExpressionLanguageTest extends \PHPUnit_Framework_TestCase
$expressionLanguage = new ExpressionLanguage();
$this->assertEquals('constant("PHP_VERSION")', $expressionLanguage->compile('constant("PHP_VERSION")'));
}
/**
* @dataProvider shortCircuitProviderEvaluate
*/
public function testShortCircuitOperatorsEvaluate($expression, array $values, $expected)
{
$expressionLanguage = new ExpressionLanguage();
$this->assertEquals($expected, $expressionLanguage->evaluate($expression, $values));
}
/**
* @dataProvider shortCircuitProviderCompile
*/
public function testShortCircuitOperatorsCompile($expression, array $names, $expected)
{
$result = null;
$expressionLanguage = new ExpressionLanguage();
eval(sprintf('$result = %s;', $expressionLanguage->compile($expression, $names)));
$this->assertSame($expected, $result);
}
public function shortCircuitProviderEvaluate()
{
$object = $this->getMockBuilder('stdClass')->setMethods(array('foo'))->getMock();
$object->expects($this->never())->method('foo');
return array(
array('false and object.foo()', array('object' => $object), false),
array('false && object.foo()', array('object' => $object), false),
array('true || object.foo()', array('object' => $object), true),
array('true or object.foo()', array('object' => $object), true),
);
}
public function shortCircuitProviderCompile()
{
return array(
array('false and foo', array('foo' => 'foo'), false),
array('false && foo', array('foo' => 'foo'), false),
array('true || foo', array('foo' => 'foo'), true),
array('true or foo', array('foo' => 'foo'), true),
);
}
}