Skip to content

Commit

Permalink
added optimized versions of expressions
Browse files Browse the repository at this point in the history
  • Loading branch information
fabpot committed Sep 19, 2013
1 parent 984bd38 commit 1bcfb40
Show file tree
Hide file tree
Showing 5 changed files with 135 additions and 14 deletions.
Expand Up @@ -24,6 +24,7 @@
use Symfony\Component\DependencyInjection\Parameter;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\ExpressionLanguage\Expression;
use Symfony\Component\Security\Core\Authorization\ExpressionLanguage;

/**
* SecurityExtension.
Expand All @@ -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()
{
Expand Down Expand Up @@ -610,9 +612,10 @@ private function createExpression($container, $expression)
}

$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);
Expand Down Expand Up @@ -676,4 +679,16 @@ public function getConfiguration(array $config, ContainerBuilder $container)
// 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;
}
}
2 changes: 1 addition & 1 deletion src/Symfony/Component/ExpressionLanguage/Expression.php
Expand Up @@ -18,7 +18,7 @@
*/
class Expression
{
private $expression;
protected $expression;

/**
* Constructor.
Expand Down
47 changes: 35 additions & 12 deletions src/Symfony/Component/ExpressionLanguage/ExpressionLanguage.php
Expand Up @@ -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.
*
Expand Down Expand Up @@ -44,9 +46,41 @@ public function compile($expression, $names = array())
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)
Expand Down Expand Up @@ -89,15 +123,4 @@ private function getCompiler()

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];
}
}
42 changes: 42 additions & 0 deletions src/Symfony/Component/ExpressionLanguage/ParsedExpression.php
@@ -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;
}
}
@@ -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);
}
}

0 comments on commit 1bcfb40

Please sign in to comment.