[ExpressionLanguage] added ExpressionFunction and ExpressionFunctionProviderInterface

This commit is contained in:
Fabien Potencier 2014-09-23 17:21:31 +02:00
parent cc04ce15c0
commit 184742c7a9
6 changed files with 152 additions and 13 deletions

View File

@ -1,6 +1,11 @@
CHANGELOG
=========
2.6.0
-----
* Added ExpressionFunction and ExpressionFunctionProviderInterface
2.4.0
-----

View File

@ -0,0 +1,65 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\ExpressionLanguage;
/**
* Represents a function that can be used in an expression.
*
* A function is defined by two PHP callables. The callables are used
* by the language to compile and/or evaluate the function.
*
* The "compiler" function is used at compilation time and must return a
* PHP representation of the function call (it receives the function
* arguments as arguments).
*
* The "evaluator" function is used for expression evaluation and must return
* the value of the function call based on the values defined for the
* expression (it receives the values as a first argument and the function
* arguments as remaining arguments).
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class ExpressionFunction
{
private $name;
private $compiler;
private $evaluator;
/**
* Constructor.
*
* @param string $name The function name
* @param callable $compiler A callable able to compile the function
* @param callable $evaluator A callable able to evaluate the function
*/
public function __construct($name, $compiler, $evaluator)
{
$this->name = $name;
$this->compiler = $compiler;
$this->evaluator = $evaluator;
}
public function getName()
{
return $this->name;
}
public function getCompiler()
{
return $this->compiler;
}
public function getEvaluator()
{
return $this->evaluator;
}
}

View File

@ -0,0 +1,23 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\ExpressionLanguage;
/**
* @author Fabien Potencier <fabien@symfony.com>
*/
interface ExpressionFunctionProviderInterface
{
/**
* @return ExpressionFunction[] An array of Function instances
*/
public function getFunctions();
}

View File

@ -31,10 +31,17 @@ class ExpressionLanguage
protected $functions = array();
public function __construct(ParserCacheInterface $cache = null)
/**
* @param ParserCacheInterface $cache
* @param ExpressionFunctionProviderInterface[] $providers
*/
public function __construct(ParserCacheInterface $cache = null, array $providers = array())
{
$this->cache = $cache ?: new ArrayParserCache();
$this->registerFunctions();
foreach ($providers as $provider) {
$this->registerProvider($provider);
}
}
/**
@ -92,27 +99,29 @@ class ExpressionLanguage
/**
* Registers a function.
*
* A function is defined by two PHP callables. The callables are used
* by the language to compile and/or evaluate the function.
*
* The first function is used at compilation time and must return a
* PHP representation of the function call (it receives the function
* arguments as arguments).
*
* The second function is used for expression evaluation and must return
* the value of the function call based on the values defined for the
* expression (it receives the values as a first argument and the function
* arguments as remaining arguments).
*
* @param string $name The function name
* @param callable $compiler A callable able to compile the function
* @param callable $evaluator A callable able to evaluate the function
*
* @see ExpressionFunction
*/
public function register($name, $compiler, $evaluator)
{
$this->functions[$name] = array('compiler' => $compiler, 'evaluator' => $evaluator);
}
public function addFunction(ExpressionFunction $function)
{
$this->register($function->getName(), $function->getCompiler(), $function->getEvaluator());
}
public function registerProvider(ExpressionFunctionProviderInterface $provider)
{
foreach ($provider->getFunctions() as $function) {
$this->addFunction($function);
}
}
protected function registerFunctions()
{
$this->register('constant', function ($constant) {

View File

@ -12,6 +12,7 @@
namespace Symfony\Component\ExpressionLanguage\Tests;
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
use Symfony\Component\ExpressionLanguage\Tests\Fixtures\TestProvider;
class ExpressionLanguageTest extends \PHPUnit_Framework_TestCase
{
@ -54,6 +55,13 @@ class ExpressionLanguageTest extends \PHPUnit_Framework_TestCase
$this->assertEquals('constant("PHP_VERSION")', $expressionLanguage->compile('constant("PHP_VERSION")'));
}
public function testProviders()
{
$expressionLanguage = new ExpressionLanguage(null, array(new TestProvider));
$this->assertEquals('foo', $expressionLanguage->evaluate('identity("foo")'));
$this->assertEquals('"foo"', $expressionLanguage->compile('identity("foo")'));
}
/**
* @dataProvider shortCircuitProviderEvaluate
*/

View File

@ -0,0 +1,29 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\ExpressionLanguage\Tests\Fixtures;
use Symfony\Component\ExpressionLanguage\ExpressionFunction;
use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface;
class TestProvider implements ExpressionFunctionProviderInterface
{
public function getFunctions()
{
return array(
new ExpressionFunction('identity', function ($input) {
return $input;
}, function (array $values, $input) {
return $input;
}),
);
}
}