Skip to content

Commit

Permalink
Merge branch '3.4' into 4.4
Browse files Browse the repository at this point in the history
* 3.4:
  [ExpressionLanguage] Fixed collisions of character operators with object properties
  [Validator] Remove specific check for Valid targets
  [PhpUnitBridge] Use trait instead of extending deprecated class
  fix remember me
  Use strict assertion in asset tests
  [DoctrineBridge][DoctrineExtractor] Fix indexBy with custom and some core types
  Do not rely on the current locale when dumping a Graphviz object
  fix typo
  [Ldap] force default network timeout
  [Config] don't throw on missing excluded paths
  Docs: Typo, grammar
  [Validator] Add the missing translations for the Polish ("pl") locale
  [Console] Inline exact-match handling with 4.4
  Set previous exception when rethrown from controller resolver
  [VarDumper] fixed DateCaster not displaying additional fields
  [HttpKernel] fix registering DebugHandlersListener regardless of the PHP_SAPI
  • Loading branch information
fabpot committed Feb 24, 2020
2 parents 58a8254 + e186bec commit 70649e0
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 4 deletions.
2 changes: 1 addition & 1 deletion Lexer.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ public function tokenize($expression)
// strings
$tokens[] = new Token(Token::STRING_TYPE, stripcslashes(substr($match[0], 1, -1)), $cursor + 1);
$cursor += \strlen($match[0]);
} elseif (preg_match('/not in(?=[\s(])|\!\=\=|not(?=[\s(])|and(?=[\s(])|\=\=\=|\>\=|or(?=[\s(])|\<\=|\*\*|\.\.|in(?=[\s(])|&&|\|\||matches|\=\=|\!\=|\*|~|%|\/|\>|\||\!|\^|&|\+|\<|\-/A', $expression, $match, 0, $cursor)) {
} elseif (preg_match('/(?<=^|[\s(])not in(?=[\s(])|\!\=\=|(?<=^|[\s(])not(?=[\s(])|(?<=^|[\s(])and(?=[\s(])|\=\=\=|\>\=|(?<=^|[\s(])or(?=[\s(])|\<\=|\*\*|\.\.|(?<=^|[\s(])in(?=[\s(])|&&|\|\||(?<=^|[\s(])matches|\=\=|\!\=|\*|~|%|\/|\>|\||\!|\^|&|\+|\<|\-/A', $expression, $match, 0, $cursor)) {
// operators
$tokens[] = new Token(Token::OPERATOR_TYPE, $match[0], $cursor + 1);
$cursor += \strlen($match[0]);
Expand Down
10 changes: 7 additions & 3 deletions Resources/bin/generate_operator_regex.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,13 @@

$regex = [];
foreach ($operators as $operator => $length) {
// an operator that ends with a character must be followed by
// a whitespace or a parenthesis
$regex[] = preg_quote($operator, '/').(ctype_alpha($operator[$length - 1]) ? '(?=[\s(])' : '');
// Collisions of character operators:
// - an operator that begins with a character must have a space or a parenthesis before or starting at the beginning of a string
// - an operator that ends with a character must be followed by a whitespace or a parenthesis
$regex[] =
(ctype_alpha($operator[0]) ? '(?<=^|[\s(])' : '')
.preg_quote($operator, '/')
.(ctype_alpha($operator[$length - 1]) ? '(?=[\s(])' : '');
}

echo '/'.implode('|', $regex).'/A';
11 changes: 11 additions & 0 deletions Tests/ExpressionLanguageTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,17 @@ public function testCachingWithDifferentNamesOrder()
$expressionLanguage->compile($expression, ['B' => 'b', 'a']);
}

public function testOperatorCollisions()
{
$expressionLanguage = new ExpressionLanguage();
$expression = 'foo.not in [bar]';
$compiled = $expressionLanguage->compile($expression, ['foo', 'bar']);
$this->assertSame('in_array($foo->not, [0 => $bar])', $compiled);

$result = $expressionLanguage->evaluate($expression, ['foo' => (object) ['not' => 'test'], 'bar' => 'test']);
$this->assertTrue($result);
}

/**
* @dataProvider getRegisterCallbacks
*/
Expand Down
12 changes: 12 additions & 0 deletions Tests/LexerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,18 @@ public function getTokenizeData()
[new Token('string', '#foo', 1)],
'"#foo"',
],
[
[
new Token('name', 'foo', 1),
new Token('punctuation', '.', 4),
new Token('name', 'not', 5),
new Token('operator', 'in', 9),
new Token('punctuation', '[', 12),
new Token('name', 'bar', 13),
new Token('punctuation', ']', 16),
],
'foo.not in [bar]',
],
];
}
}
33 changes: 33 additions & 0 deletions Tests/ParserTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ public function getParseData()
$arguments->addElement(new Node\ConstantNode(2));
$arguments->addElement(new Node\ConstantNode(true));

$arrayNode = new Node\ArrayNode();
$arrayNode->addElement(new Node\NameNode('bar'));

return [
[
new Node\NameNode('a'),
Expand Down Expand Up @@ -151,6 +154,36 @@ public function getParseData()
'bar',
['foo' => 'bar'],
],

// Operators collisions
[
new Node\BinaryNode(
'in',
new Node\GetAttrNode(
new Node\NameNode('foo'),
new Node\ConstantNode('not', true),
new Node\ArgumentsNode(),
Node\GetAttrNode::PROPERTY_CALL
),
$arrayNode
),
'foo.not in [bar]',
['foo', 'bar'],
],
[
new Node\BinaryNode(
'or',
new Node\UnaryNode('not', new Node\NameNode('foo')),
new Node\GetAttrNode(
new Node\NameNode('foo'),
new Node\ConstantNode('not', true),
new Node\ArgumentsNode(),
Node\GetAttrNode::PROPERTY_CALL
)
),
'not foo or foo.not',
['foo'],
],
];
}

Expand Down

0 comments on commit 70649e0

Please sign in to comment.