merged branch adrienbrault/expression-cache (PR #9095)
This PR was squashed before being merged into the master branch (closes #9095).
Discussion
----------
[ExpressionLanguage] Introduce a ParserCacheInterface with array/doctrine implementations
| Q | A
| ------------- | ---
| Bug fix? | no
| New feature? | yes
| BC breaks? | no
| Deprecations? | no
| Tests pass? | yes
| Fixed tickets | N/A
| License | MIT
| Doc PR | N/A
Commits
-------
c8e6799
[ExpressionLanguage] Introduce a ParserCacheInterface with array/doctrine implementations
This commit is contained in:
commit
db00c3f510
@ -0,0 +1,48 @@
|
||||
<?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\Bridge\Doctrine\ExpressionLanguage;
|
||||
|
||||
use Doctrine\Common\Cache\Cache;
|
||||
use Symfony\Component\ExpressionLanguage\ParsedExpression;
|
||||
use Symfony\Component\ExpressionLanguage\ParserCache\ParserCacheInterface;
|
||||
|
||||
/**
|
||||
* @author Adrien Brault <adrien.brault@gmail.com>
|
||||
*/
|
||||
class DoctrineParserCache implements ParserCacheInterface
|
||||
{
|
||||
/**
|
||||
* @var Cache
|
||||
*/
|
||||
private $cache;
|
||||
|
||||
public function __construct(Cache $cache)
|
||||
{
|
||||
$this->cache = $cache;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function fetch($key)
|
||||
{
|
||||
return $this->cache->fetch($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function save($key, ParsedExpression $expression)
|
||||
{
|
||||
$this->cache->save($key, $expression);
|
||||
}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Bridge\Doctrine\Tests\ExpressionLanguage;
|
||||
|
||||
use Symfony\Bridge\Doctrine\ExpressionLanguage\DoctrineParserCache;
|
||||
|
||||
class DoctrineParserCacheTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testFetch()
|
||||
{
|
||||
$doctrineCacheMock = $this->getMock('Doctrine\Common\Cache\Cache');
|
||||
$parserCache = new DoctrineParserCache($doctrineCacheMock);
|
||||
|
||||
$doctrineCacheMock->expects($this->once())
|
||||
->method('fetch')
|
||||
->will($this->returnValue('bar'));
|
||||
|
||||
$result = $parserCache->fetch('foo');
|
||||
|
||||
$this->assertEquals('bar', $result);
|
||||
}
|
||||
|
||||
public function testSave()
|
||||
{
|
||||
$doctrineCacheMock = $this->getMock('Doctrine\Common\Cache\Cache');
|
||||
$parserCache = new DoctrineParserCache($doctrineCacheMock);
|
||||
|
||||
$expression = $this->getMockBuilder('Symfony\Component\ExpressionLanguage\ParsedExpression')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$doctrineCacheMock->expects($this->once())
|
||||
->method('save')
|
||||
->with('foo', $expression);
|
||||
|
||||
$parserCache->save('foo', $expression);
|
||||
}
|
||||
}
|
@ -11,7 +11,8 @@
|
||||
|
||||
namespace Symfony\Component\ExpressionLanguage;
|
||||
|
||||
use Symfony\Component\ExpressionLanguage\Node\Node;
|
||||
use Symfony\Component\ExpressionLanguage\ParserCache\ArrayParserCache;
|
||||
use Symfony\Component\ExpressionLanguage\ParserCache\ParserCacheInterface;
|
||||
|
||||
/**
|
||||
* Allows to compile and evaluate expressions written in your own DSL.
|
||||
@ -20,15 +21,20 @@ use Symfony\Component\ExpressionLanguage\Node\Node;
|
||||
*/
|
||||
class ExpressionLanguage
|
||||
{
|
||||
/**
|
||||
* @var ParserCacheInterface
|
||||
*/
|
||||
private $parserCache;
|
||||
|
||||
private $lexer;
|
||||
private $parser;
|
||||
private $compiler;
|
||||
private $cache;
|
||||
|
||||
protected $functions;
|
||||
|
||||
public function __construct()
|
||||
public function __construct(ParserCacheInterface $parserCache = null)
|
||||
{
|
||||
$this->parserCache = $parserCache ?: new ArrayParserCache();
|
||||
$this->functions = array();
|
||||
$this->registerFunctions();
|
||||
}
|
||||
@ -74,12 +80,14 @@ class ExpressionLanguage
|
||||
|
||||
$key = $expression.'//'.implode('-', $names);
|
||||
|
||||
if (!isset($this->cache[$key])) {
|
||||
if (null === $parsedExpression = $this->parserCache->fetch($key)) {
|
||||
$nodes = $this->getParser()->parse($this->getLexer()->tokenize((string) $expression), $names);
|
||||
$this->cache[$key] = new ParsedExpression((string) $expression, $nodes);
|
||||
$parsedExpression = new ParsedExpression((string) $expression, $nodes);
|
||||
|
||||
$this->parserCache->save($key, $parsedExpression);
|
||||
}
|
||||
|
||||
return $this->cache[$key];
|
||||
return $parsedExpression;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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\ParserCache;
|
||||
|
||||
use Symfony\Component\ExpressionLanguage\ParsedExpression;
|
||||
|
||||
/**
|
||||
* @author Adrien Brault <adrien.brault@gmail.com>
|
||||
*/
|
||||
class ArrayParserCache implements ParserCacheInterface
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $cache = array();
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function fetch($key)
|
||||
{
|
||||
return isset($this->cache[$key]) ? $this->cache[$key] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function save($key, ParsedExpression $expression)
|
||||
{
|
||||
$this->cache[$key] = $expression;
|
||||
}
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
<?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\ParserCache;
|
||||
|
||||
use Symfony\Component\ExpressionLanguage\ParsedExpression;
|
||||
|
||||
/**
|
||||
* @author Adrien Brault <adrien.brault@gmail.com>
|
||||
*/
|
||||
interface ParserCacheInterface
|
||||
{
|
||||
/**
|
||||
* @param string $key
|
||||
* @param ParsedExpression $data
|
||||
*/
|
||||
public function save($key, ParsedExpression $expression);
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
* @return ParsedExpression|null
|
||||
*/
|
||||
public function fetch($key);
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\ExpressionLanguage\Tests;
|
||||
|
||||
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
|
||||
use Symfony\Component\ExpressionLanguage\ParsedExpression;
|
||||
|
||||
class ExpressionLanguageTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testCachedParse()
|
||||
{
|
||||
$cacheMock = $this->getMock('Symfony\Component\ExpressionLanguage\ParserCache\ParserCacheInterface');
|
||||
$savedParsedExpression = null;
|
||||
$expressionLanguage = new ExpressionLanguage($cacheMock);
|
||||
|
||||
$cacheMock
|
||||
->expects($this->exactly(2))
|
||||
->method('fetch')
|
||||
->with('1 + 1//')
|
||||
->will($this->returnCallback(function () use (&$savedParsedExpression) {
|
||||
return $savedParsedExpression;
|
||||
}))
|
||||
;
|
||||
$cacheMock
|
||||
->expects($this->exactly(1))
|
||||
->method('save')
|
||||
->with('1 + 1//', $this->isInstanceOf('Symfony\Component\ExpressionLanguage\ParsedExpression'))
|
||||
->will($this->returnCallback(function ($key, $expression) use (&$savedParsedExpression) {
|
||||
$savedParsedExpression = $expression;
|
||||
}))
|
||||
;
|
||||
|
||||
$parsedExpression = $expressionLanguage->parse('1 + 1', array());
|
||||
$this->assertSame($savedParsedExpression, $parsedExpression);
|
||||
|
||||
$parsedExpression = $expressionLanguage->parse('1 + 1', array());
|
||||
$this->assertSame($savedParsedExpression, $parsedExpression);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user