bug #15552 [ExpressionLanguage] Fixed expressions cache key generation (inso)

This PR was squashed before being merged into the 2.7 branch (closes #15552).

Discussion
----------

[ExpressionLanguage] Fixed expressions cache key generation

| Q             | A
| ------------- | ---
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | n/a
| License       | MIT
| Doc PR        | n/a

Reworked version of #15537

Difference with original PR:
- sort $names array to ensure its order does not affect caching, added test for it
- minor tweaks for cache key format
- used `foreach` instead of `array_map`

P.S. I'm not proficient with tests so not sure if tests are correct.

Commits
-------

4114a2b [ExpressionLanguage] Fixed expressions cache key generation
This commit is contained in:
Fabien Potencier 2015-09-07 14:45:05 +02:00
commit 72615e11a2
2 changed files with 42 additions and 1 deletions

View File

@ -84,7 +84,14 @@ class ExpressionLanguage
return $expression;
}
$key = $expression.'//'.implode('-', $names);
asort($names);
$cacheKeyItems = array();
foreach ($names as $nameKey => $name) {
$cacheKeyItems[] = is_int($nameKey) ? $name : $nameKey.':'.$name;
}
$key = $expression.'//'.implode('|', $cacheKeyItems);
if (null === $parsedExpression = $this->cache->fetch($key)) {
$nodes = $this->getParser()->parse($this->getLexer()->tokenize((string) $expression), $names);

View File

@ -104,4 +104,38 @@ class ExpressionLanguageTest extends \PHPUnit_Framework_TestCase
array('true or foo', array('foo' => 'foo'), true),
);
}
public function testCachingForOverriddenVariableNames()
{
$expressionLanguage = new ExpressionLanguage();
$expression = 'a + b';
$expressionLanguage->evaluate($expression, array('a' => 1, 'b' => 1));
$result = $expressionLanguage->compile($expression, array('a', 'B' => 'b'));
$this->assertSame('($a + $B)', $result);
}
public function testCachingWithDifferentNamesOrder()
{
$cacheMock = $this->getMock('Symfony\Component\ExpressionLanguage\ParserCache\ParserCacheInterface');
$expressionLanguage = new ExpressionLanguage($cacheMock);
$savedParsedExpressions = array();
$cacheMock
->expects($this->exactly(2))
->method('fetch')
->will($this->returnCallback(function ($key) use (&$savedParsedExpressions) {
return isset($savedParsedExpressions[$key]) ? $savedParsedExpressions[$key] : null;
}))
;
$cacheMock
->expects($this->exactly(1))
->method('save')
->will($this->returnCallback(function ($key, $expression) use (&$savedParsedExpressions) {
$savedParsedExpressions[$key] = $expression;
}))
;
$expression = 'a + b';
$expressionLanguage->compile($expression, array('a', 'B' => 'b'));
$expressionLanguage->compile($expression, array('B' => 'b', 'a'));
}
}