James Cole
2025-10-30 20:46:43 +01:00
parent e1e18a2a0c
commit 2aabb56d2d

View File

@@ -52,13 +52,23 @@ class QueryParser implements QueryParserInterface
$inQuotes = false; $inQuotes = false;
$fieldName = ''; $fieldName = '';
$prohibited = false; $prohibited = false;
$chrArray = preg_split('//u', $this->query, -1, PREG_SPLIT_NO_EMPTY);
while ($this->position < strlen($this->query)) { $count = count($chrArray);
$char = $this->query[$this->position]; while ($this->position < $count) {
$char = $chrArray[$this->position];
$nextChar = $chrArray[$this->position + 1] ?? '';
// Log::debug(sprintf('Char #%d: %s', $this->position, $char)); // Log::debug(sprintf('Char #%d: %s', $this->position, $char));
// If we're in a quoted string, we treat all characters except another quote as ordinary characters // If we're in a quoted string, we treat all characters except another quote as ordinary characters
if ($inQuotes) { if ($inQuotes) {
if ('\\' === $char && '"' === $nextChar) {
// Log::debug('BACKSLASH!');
// escaped quote, pretend it's a normal char and continue two places (skipping the actual character).
$tokenUnderConstruction .= '\\' . $nextChar;
$this->position += 2;
continue;
}
if ('"' !== $char) { if ('"' !== $char) {
$tokenUnderConstruction .= $char; $tokenUnderConstruction .= $char;
++$this->position; ++$this->position;
@@ -67,11 +77,9 @@ class QueryParser implements QueryParserInterface
} }
// char is " // char is "
++$this->position; ++$this->position;
Log::debug(sprintf('Constructed token: %s', $tokenUnderConstruction));
return new NodeResult( return new NodeResult($this->createNode($tokenUnderConstruction, $fieldName, $prohibited), false);
$this->createNode($tokenUnderConstruction, $fieldName, $prohibited),
false
);
} }
switch ($char) { switch ($char) {
@@ -139,7 +147,7 @@ class QueryParser implements QueryParserInterface
if ('' === $tokenUnderConstruction) { if ('' === $tokenUnderConstruction) {
// In any other location, it's just a normal character // In any other location, it's just a normal character
$tokenUnderConstruction .= $char; $tokenUnderConstruction .= $char;
$skipNext = true; $skipNext = true;
} }
if ('' !== $tokenUnderConstruction && !$skipNext) { // @phpstan-ignore-line if ('' !== $tokenUnderConstruction && !$skipNext) { // @phpstan-ignore-line
Log::debug(sprintf('Turns out that "%s" is a field name. Reset the token.', $tokenUnderConstruction)); Log::debug(sprintf('Turns out that "%s" is a field name. Reset the token.', $tokenUnderConstruction));
@@ -171,7 +179,7 @@ class QueryParser implements QueryParserInterface
++$this->position; ++$this->position;
} }
$finalNode = '' !== $tokenUnderConstruction || '' !== $fieldName $finalNode = '' !== $tokenUnderConstruction || '' !== $fieldName
? $this->createNode($tokenUnderConstruction, $fieldName, $prohibited) ? $this->createNode($tokenUnderConstruction, $fieldName, $prohibited)
: null; : null;
@@ -184,7 +192,7 @@ class QueryParser implements QueryParserInterface
$nodeResult = $this->buildNextNode($isSubquery); $nodeResult = $this->buildNextNode($isSubquery);
while ($nodeResult->node instanceof Node) { while ($nodeResult->node instanceof Node) {
$nodes[] = $nodeResult->node; $nodes[] = $nodeResult->node;
if ($nodeResult->isSubqueryEnd) { if ($nodeResult->isSubqueryEnd) {
break; break;
} }
@@ -197,9 +205,13 @@ class QueryParser implements QueryParserInterface
private function createNode(string $token, string $fieldName, bool $prohibited): Node private function createNode(string $token, string $fieldName, bool $prohibited): Node
{ {
if ('' !== $fieldName) { if ('' !== $fieldName) {
Log::debug(sprintf('Create FieldNode %s:%s (%s)', $fieldName, $token, var_export($prohibited, true))); // OK dus hoe trim je \" correct?
$token = ltrim($token, ':"'); $token = ltrim($token, ':"');
$token = rtrim($token, '"'); if (!str_ends_with($token, '\\"')) {
$token = rtrim($token, '"');
}
$token = str_replace('\\"', '"', $token);
Log::debug(sprintf('Create FieldNode %s:%s (%s)', $fieldName, $token, var_export($prohibited, true)));
return new FieldNode(trim($fieldName), trim($token), $prohibited); return new FieldNode(trim($fieldName), trim($token), $prohibited);
} }