Skip to content

Commit

Permalink
[ExpressionLanguage] Introduce a ParserCacheInterface with array/doct…
Browse files Browse the repository at this point in the history
…rine implementations
  • Loading branch information
adrienbrault authored and fabpot committed Sep 23, 2013
1 parent b1542f0 commit c8e6799
Show file tree
Hide file tree
Showing 6 changed files with 212 additions and 6 deletions.
@@ -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);
}
}
20 changes: 14 additions & 6 deletions src/Symfony/Component/ExpressionLanguage/ExpressionLanguage.php
Expand Up @@ -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.
Expand All @@ -20,15 +21,20 @@
*/
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();
}
Expand Down Expand Up @@ -74,12 +80,14 @@ public function parse($expression, $names)

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

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

0 comments on commit c8e6799

Please sign in to comment.