Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Expression language extensibility #12006

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Sep 28, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\Reference;

/**
* Registers the expression language providers.
*
* @author Fabien Potencier <[email protected]>
*/
class AddExpressionLanguageProvidersPass implements CompilerPassInterface
{
/**
* {@inheritdoc}
*/
public function process(ContainerBuilder $container)
{
// routing
if ($container->hasDefinition('router')) {
$definition = $container->findDefinition('router');
foreach ($container->findTaggedServiceIds('routing.expression_language_provider') as $id => $attributes) {
$definition->addMethodCall('addExpressionLanguageProvider', array(new Reference($id)));
}
}

// security
if ($container->hasDefinition('security.access.expression_voter')) {
$definition = $container->findDefinition('security.access.expression_voter');
foreach ($container->findTaggedServiceIds('security.expression_language_provider') as $id => $attributes) {
$definition->addMethodCall('addExpressionLanguageProvider', array(new Reference($id)));
}
}
}
}
2 changes: 2 additions & 0 deletions src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\LoggingTranslatorPass;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddCacheWarmerPass;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddCacheClearerPass;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddExpressionLanguageProvidersPass;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ContainerBuilderDebugDumpPass;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\CompilerDebugDumpPass;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TranslationExtractorPass;
Expand Down Expand Up @@ -81,6 +82,7 @@ public function build(ContainerBuilder $container)
$container->addCompilerPass(new LoggingTranslatorPass());
$container->addCompilerPass(new AddCacheWarmerPass());
$container->addCompilerPass(new AddCacheClearerPass());
$container->addCompilerPass(new AddExpressionLanguageProvidersPass());
$container->addCompilerPass(new TranslationExtractorPass());
$container->addCompilerPass(new TranslationDumperPass());
$container->addCompilerPass(new FragmentRendererPass(), PassConfig::TYPE_AFTER_REMOVING);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddExpressionLanguageProvidersPass;

class AddExpressionLanguageProvidersPassTest extends \PHPUnit_Framework_TestCase
{
public function testProcessForRouter()
{
$container = new ContainerBuilder();
$container->addCompilerPass(new AddExpressionLanguageProvidersPass());

$definition = new Definition('Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler\TestProvider');
$definition->addTag('routing.expression_language_provider');
$container->setDefinition('some_routing_provider', $definition);

$container->register('router', '\stdClass');
$container->compile();

$router = $container->getDefinition('router');
$calls = $router->getMethodCalls();
$this->assertCount(1, $calls);
$this->assertEquals('addExpressionLanguageProvider', $calls[0][0]);
$this->assertEquals(new Reference('some_routing_provider'), $calls[0][1][0]);
}

public function testProcessForSecurity()
{
$container = new ContainerBuilder();
$container->addCompilerPass(new AddExpressionLanguageProvidersPass());

$definition = new Definition('Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler\TestProvider');
$definition->addTag('security.expression_language_provider');
$container->setDefinition('some_security_provider', $definition);

$container->register('security.access.expression_voter', '\stdClass');
$container->compile();

$router = $container->getDefinition('security.access.expression_voter');
$calls = $router->getMethodCalls();
$this->assertCount(1, $calls);
$this->assertEquals('addExpressionLanguageProvider', $calls[0][0]);
$this->assertEquals(new Reference('some_security_provider'), $calls[0][1][0]);
}
}

class TestProvider
{
}
13 changes: 12 additions & 1 deletion src/Symfony/Component/DependencyInjection/ContainerBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
use Symfony\Component\DependencyInjection\LazyProxy\Instantiator\InstantiatorInterface;
use Symfony\Component\DependencyInjection\LazyProxy\Instantiator\RealServiceInstantiator;
use Symfony\Component\ExpressionLanguage\Expression;
use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface;

/**
* ContainerBuilder is a DI container that provides an API to easily describe services.
Expand Down Expand Up @@ -84,6 +85,11 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
*/
private $expressionLanguage;

/**
* @var ExpressionFunctionProviderInterface[]
*/
private $expressionLanguageProviders = array();

/**
* Sets the track resources flag.
*
Expand Down Expand Up @@ -1056,6 +1062,11 @@ public function findTags()
return array_unique($tags);
}

public function addExpressionLanguageProvider(ExpressionFunctionProviderInterface $provider)
{
$this->expressionLanguageProviders[] = $provider;
}

/**
* Returns the Service Conditionals.
*
Expand Down Expand Up @@ -1161,7 +1172,7 @@ private function getExpressionLanguage()
if (!class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage')) {
throw new RuntimeException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.');
}
$this->expressionLanguage = new ExpressionLanguage();
$this->expressionLanguage = new ExpressionLanguage(null, $this->expressionLanguageProviders);
}

return $this->expressionLanguage;
Expand Down
13 changes: 12 additions & 1 deletion src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
use Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\NullDumper;
use Symfony\Component\DependencyInjection\ExpressionLanguage;
use Symfony\Component\ExpressionLanguage\Expression;
use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface;

/**
* PhpDumper dumps a service container as a PHP class.
Expand Down Expand Up @@ -55,6 +56,11 @@ class PhpDumper extends Dumper
private $reservedVariables = array('instance', 'class');
private $expressionLanguage;

/**
* @var ExpressionFunctionProviderInterface[]
*/
private $expressionLanguageProviders = array();

/**
* @var \Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\DumperInterface
*/
Expand Down Expand Up @@ -1335,6 +1341,11 @@ public function dumpParameter($name)
return sprintf("\$this->getParameter('%s')", strtolower($name));
}

public function addExpressionLanguageProvider(ExpressionFunctionProviderInterface $provider)
{
$this->expressionLanguageProviders[] = $provider;
}

/**
* Gets a service call
*
Expand Down Expand Up @@ -1424,7 +1435,7 @@ private function getExpressionLanguage()
if (!class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage')) {
throw new RuntimeException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.');
}
$this->expressionLanguage = new ExpressionLanguage();
$this->expressionLanguage = new ExpressionLanguage(null, $this->expressionLanguageProviders);
}

return $this->expressionLanguage;
Expand Down
23 changes: 7 additions & 16 deletions src/Symfony/Component/DependencyInjection/ExpressionLanguage.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,31 +12,22 @@
namespace Symfony\Component\DependencyInjection;

use Symfony\Component\ExpressionLanguage\ExpressionLanguage as BaseExpressionLanguage;
use Symfony\Component\ExpressionLanguage\ParserCache\ParserCacheInterface;

/**
* Adds some function to the default ExpressionLanguage.
*
* To get a service, use service('request').
* To get a parameter, use parameter('kernel.debug').
*
* @author Fabien Potencier <[email protected]>
*
* @see ExpressionLanguageProvider
*/
class ExpressionLanguage extends BaseExpressionLanguage
{
protected function registerFunctions()
public function __construct(ParserCacheInterface $cache = null, array $providers = array())
{
parent::registerFunctions();

$this->register('service', function ($arg) {
return sprintf('$this->get(%s)', $arg);
}, function (array $variables, $value) {
return $variables['container']->get($value);
});
// prepend the default provider to let users overide it easily
array_unshift($providers, new ExpressionLanguageProvider());

$this->register('parameter', function ($arg) {
return sprintf('$this->getParameter(%s)', $arg);
}, function (array $variables, $value) {
return $variables['container']->getParameter($value);
});
parent::__construct($cache, $providers);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\DependencyInjection;

use Symfony\Component\ExpressionLanguage\ExpressionFunction;
use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface;

/**
* Define some ExpressionLanguage functions.
*
* To get a service, use service('request').
* To get a parameter, use parameter('kernel.debug').
*
* @author Fabien Potencier <[email protected]>
*/
class ExpressionLanguageProvider implements ExpressionFunctionProviderInterface
{
public function getFunctions()
{
return array(
new ExpressionFunction('service', function ($arg) {
return sprintf('$this->get(%s)', $arg);
}, function (array $variables, $value) {
return $variables['container']->get($value);
}),

new ExpressionFunction('parameter', function ($arg) {
return sprintf('$this->getParameter(%s)', $arg);
}, function (array $variables, $value) {
return $variables['container']->getParameter($value);
}),
);
}
}
5 changes: 5 additions & 0 deletions src/Symfony/Component/ExpressionLanguage/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
CHANGELOG
=========

2.6.0
-----

* Added ExpressionFunction and ExpressionFunctionProviderInterface

2.4.0
-----

Expand Down
65 changes: 65 additions & 0 deletions src/Symfony/Component/ExpressionLanguage/ExpressionFunction.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <[email protected]>
*
* 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 <[email protected]>
*/
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;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <[email protected]>
*
* 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 <[email protected]>
*/
interface ExpressionFunctionProviderInterface
{
/**
* @return ExpressionFunction[] An array of Function instances
*/
public function getFunctions();
}
Loading