[ExpressionLanguage] Introduce a ParserCacheInterface with array/doctrine implementations

This commit is contained in:
Adrien Brault 2013-09-22 16:48:20 -07:00 committed by Fabien Potencier
parent b1542f0620
commit c8e679970e
6 changed files with 212 additions and 6 deletions

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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;
}
/**

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\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;
}
}

View File

@ -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);
}

View File

@ -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);
}
}