added optimized versions of expressions

This commit is contained in:
Fabien Potencier 2013-09-06 08:52:21 +02:00
parent 984bd38568
commit 1bcfb40eb5
5 changed files with 135 additions and 14 deletions

View File

@ -24,6 +24,7 @@ use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\Parameter; use Symfony\Component\DependencyInjection\Parameter;
use Symfony\Component\Config\FileLocator; use Symfony\Component\Config\FileLocator;
use Symfony\Component\ExpressionLanguage\Expression; use Symfony\Component\ExpressionLanguage\Expression;
use Symfony\Component\Security\Core\Authorization\ExpressionLanguage;
/** /**
* SecurityExtension. * SecurityExtension.
@ -39,6 +40,7 @@ class SecurityExtension extends Extension
private $listenerPositions = array('pre_auth', 'form', 'http', 'remember_me'); private $listenerPositions = array('pre_auth', 'form', 'http', 'remember_me');
private $factories = array(); private $factories = array();
private $userProviderFactories = array(); private $userProviderFactories = array();
private $expressionLanguage;
public function __construct() public function __construct()
{ {
@ -610,9 +612,10 @@ class SecurityExtension extends Extension
} }
$container $container
->register($id, 'Symfony\Component\ExpressionLanguage\Expression') ->register($id, 'Symfony\Component\ExpressionLanguage\SerializedParsedExpression')
->setPublic(false) ->setPublic(false)
->addArgument($expression) ->addArgument($expression)
->addArgument(serialize($this->getExpressionLanguage()->parse($expression, array('token', 'user', 'object', 'roles', 'request'))))
; ;
return $this->expressions[$id] = new Reference($id); return $this->expressions[$id] = new Reference($id);
@ -676,4 +679,16 @@ class SecurityExtension extends Extension
// first assemble the factories // first assemble the factories
return new MainConfiguration($this->factories, $this->userProviderFactories); 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;
}
} }

View File

@ -18,7 +18,7 @@ namespace Symfony\Component\ExpressionLanguage;
*/ */
class Expression class Expression
{ {
private $expression; protected $expression;
/** /**
* Constructor. * Constructor.

View File

@ -11,6 +11,8 @@
namespace Symfony\Component\ExpressionLanguage; namespace Symfony\Component\ExpressionLanguage;
use Symfony\Component\ExpressionLanguage\Node\Node;
/** /**
* Allows to compile and evaluate expressions written in your own DSL. * 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(); 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()) 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) public function addFunction($name, $compiler, $evaluator)
@ -89,15 +123,4 @@ class ExpressionLanguage
return $this->compiler->reset(); 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];
}
} }

View File

@ -0,0 +1,42 @@
<?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;
use Symfony\Component\ExpressionLanguage\Node\Node;
/**
* Represents an already parsed expression.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
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;
}
}

View File

@ -0,0 +1,41 @@
<?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;
use Symfony\Component\ExpressionLanguage\Node\Node;
/**
* Represents an already parsed expression.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
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);
}
}