diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php index f0bcdcaec9..3047136283 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php @@ -24,6 +24,7 @@ use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\Parameter; use Symfony\Component\Config\FileLocator; use Symfony\Component\ExpressionLanguage\Expression; +use Symfony\Component\Security\Core\Authorization\ExpressionLanguage; /** * SecurityExtension. @@ -39,6 +40,7 @@ class SecurityExtension extends Extension private $listenerPositions = array('pre_auth', 'form', 'http', 'remember_me'); private $factories = array(); private $userProviderFactories = array(); + private $expressionLanguage; public function __construct() { @@ -610,9 +612,10 @@ class SecurityExtension extends Extension } $container - ->register($id, 'Symfony\Component\ExpressionLanguage\Expression') + ->register($id, 'Symfony\Component\ExpressionLanguage\SerializedParsedExpression') ->setPublic(false) ->addArgument($expression) + ->addArgument(serialize($this->getExpressionLanguage()->parse($expression, array('token', 'user', 'object', 'roles', 'request')))) ; return $this->expressions[$id] = new Reference($id); @@ -676,4 +679,16 @@ class SecurityExtension extends Extension // first assemble the factories return new MainConfiguration($this->factories, $this->userProviderFactories); } + + private function getExpressionLanguage() + { + if (null === $this->expressionLanguage) { + 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(); + } + + return $this->expressionLanguage; + } } diff --git a/src/Symfony/Component/ExpressionLanguage/Expression.php b/src/Symfony/Component/ExpressionLanguage/Expression.php index a1ddc362bc..f5a3820309 100644 --- a/src/Symfony/Component/ExpressionLanguage/Expression.php +++ b/src/Symfony/Component/ExpressionLanguage/Expression.php @@ -18,7 +18,7 @@ namespace Symfony\Component\ExpressionLanguage; */ class Expression { - private $expression; + protected $expression; /** * Constructor. diff --git a/src/Symfony/Component/ExpressionLanguage/ExpressionLanguage.php b/src/Symfony/Component/ExpressionLanguage/ExpressionLanguage.php index dfd8018c57..0a45ca14dd 100644 --- a/src/Symfony/Component/ExpressionLanguage/ExpressionLanguage.php +++ b/src/Symfony/Component/ExpressionLanguage/ExpressionLanguage.php @@ -11,6 +11,8 @@ namespace Symfony\Component\ExpressionLanguage; +use Symfony\Component\ExpressionLanguage\Node\Node; + /** * Allows to compile and evaluate expressions written in your own DSL. * @@ -44,9 +46,41 @@ class ExpressionLanguage return $this->getCompiler()->compile($this->parse($expression, $names))->getSource(); } + /** + * Evaluate an expression. + * + * @param Expression|string $expression The expression to compile + * @param array $values An array of values + * + * @return string The result of the evaluation of the expression + */ public function evaluate($expression, $values = array()) { - return $this->parse($expression, array_keys($values))->evaluate($this->functions, $values); + if ($expression instanceof ParsedExpression) { + $expression = $expression->getNodes(); + } else { + $expression = $this->parse($expression, array_keys($values)); + } + + return $expression->evaluate($this->functions, $values); + } + + /** + * Parses an expression. + * + * @param Expression|string $expression The expression to parse + * + * @return Node A Node tree + */ + public function parse($expression, $names) + { + $key = $expression.'//'.implode('-', $names); + + if (!isset($this->cache[$key])) { + $this->cache[$key] = $this->getParser()->parse($this->getLexer()->tokenize((string) $expression), $names); + } + + return $this->cache[$key]; } public function addFunction($name, $compiler, $evaluator) @@ -89,15 +123,4 @@ class ExpressionLanguage return $this->compiler->reset(); } - - private function parse($expression, $names) - { - $key = $expression.'//'.implode('-', $names); - - if (!isset($this->cache[$key])) { - $this->cache[$key] = $this->getParser()->parse($this->getLexer()->tokenize((string) $expression), $names); - } - - return $this->cache[$key]; - } } diff --git a/src/Symfony/Component/ExpressionLanguage/ParsedExpression.php b/src/Symfony/Component/ExpressionLanguage/ParsedExpression.php new file mode 100644 index 0000000000..61bf5807c4 --- /dev/null +++ b/src/Symfony/Component/ExpressionLanguage/ParsedExpression.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\ExpressionLanguage; + +use Symfony\Component\ExpressionLanguage\Node\Node; + +/** + * Represents an already parsed expression. + * + * @author Fabien Potencier + */ +class ParsedExpression extends Expression +{ + private $nodes; + + /** + * Constructor. + * + * @param string $expression An expression + * @param Node $nodes A Node representing the expression + */ + public function __construct($expression, Node $nodes) + { + parent::__construct($expression); + + $this->nodes = $nodes; + } + + public function getNodes() + { + return $this->nodes; + } +} diff --git a/src/Symfony/Component/ExpressionLanguage/SerializedParsedExpression.php b/src/Symfony/Component/ExpressionLanguage/SerializedParsedExpression.php new file mode 100644 index 0000000000..b1b09b69b9 --- /dev/null +++ b/src/Symfony/Component/ExpressionLanguage/SerializedParsedExpression.php @@ -0,0 +1,41 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\ExpressionLanguage; + +use Symfony\Component\ExpressionLanguage\Node\Node; + +/** + * Represents an already parsed expression. + * + * @author Fabien Potencier + */ +class SerializedParsedExpression extends ParsedExpression +{ + private $nodes; + + /** + * Constructor. + * + * @param string $expression An expression + * @param string $nodes The serialized nodes for the expression + */ + public function __construct($expression, $nodes) + { + $this->expression = (string) $expression; + $this->nodes = $nodes; + } + + public function getNodes() + { + return unserialize($this->nodes); + } +}