Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
| Total | |
97.50% |
39 / 40 |
|
75.00% |
3 / 4 |
CRAP | |
0.00% |
0 / 1 |
| Expression | |
97.50% |
39 / 40 |
|
75.00% |
3 / 4 |
32 | |
0.00% |
0 / 1 |
| getOperator | |
100.00% |
17 / 17 |
|
100.00% |
1 / 1 |
18 | |||
| getOperand | |
100.00% |
14 / 14 |
|
100.00% |
1 / 1 |
9 | |||
| localeIds | |
87.50% |
7 / 8 |
|
0.00% |
0 / 1 |
3.02 | |||
| translateKeyword | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
2 | |||
| 1 | <?php |
| 2 | |
| 3 | declare(strict_types=1); |
| 4 | |
| 5 | namespace Cosray\Finder\Output; |
| 6 | |
| 7 | use Celemas\Quma\Database; |
| 8 | use Cosray\Context; |
| 9 | use Cosray\Exception\ParserException; |
| 10 | use Cosray\Finder\CompilesField; |
| 11 | use Cosray\Finder\Input\Token; |
| 12 | use Cosray\Finder\Input\TokenType; |
| 13 | |
| 14 | abstract readonly class Expression |
| 15 | { |
| 16 | use CompilesField; |
| 17 | |
| 18 | protected function getOperator(TokenType $type): string |
| 19 | { |
| 20 | return match ($type) { |
| 21 | TokenType::LeftParen => '(', |
| 22 | TokenType::RightParen => ')', |
| 23 | TokenType::Equal => '=', |
| 24 | TokenType::Greater => '>', |
| 25 | TokenType::GreaterEqual => '>=', |
| 26 | TokenType::Less => '<', |
| 27 | TokenType::LessEqual => '<=', |
| 28 | TokenType::Like => 'LIKE', |
| 29 | TokenType::ILike => 'ILIKE', |
| 30 | TokenType::Unequal => '!=', |
| 31 | TokenType::Unlike => 'NOT LIKE', |
| 32 | TokenType::IUnlike => 'NOT ILIKE', |
| 33 | TokenType::And => 'AND', |
| 34 | TokenType::Or => 'OR', |
| 35 | TokenType::In => 'IN', |
| 36 | TokenType::NotIn => 'NOT IN', |
| 37 | default => throw new ParserException('Invalid expression operator: ' . $type->name), |
| 38 | }; |
| 39 | } |
| 40 | |
| 41 | protected function getOperand( |
| 42 | #[\SensitiveParameter] |
| 43 | Token $token, |
| 44 | Database $db, |
| 45 | array $builtins, |
| 46 | ?Context $context = null, |
| 47 | ): string { |
| 48 | return match ($token->type) { |
| 49 | TokenType::Boolean => strtolower($token->lexeme), |
| 50 | TokenType::Field => $this->compileField( |
| 51 | $token->lexeme, |
| 52 | 'n.content', |
| 53 | localeIds: $this->localeIds($context), |
| 54 | ), |
| 55 | TokenType::Builtin => $builtins[$token->lexeme], |
| 56 | TokenType::Keyword => $this->translateKeyword($token->lexeme), |
| 57 | TokenType::Null => 'NULL', |
| 58 | TokenType::Number => $token->lexeme, |
| 59 | TokenType::String => $db->quote($token->lexeme), |
| 60 | TokenType::List => $token->lexeme, |
| 61 | }; |
| 62 | } |
| 63 | |
| 64 | private function localeIds(?Context $context): array |
| 65 | { |
| 66 | if (!$context) { |
| 67 | return ['zxx']; |
| 68 | } |
| 69 | |
| 70 | $ids = []; |
| 71 | $locale = $context->locale(); |
| 72 | |
| 73 | while ($locale) { |
| 74 | $ids[] = $locale->id; |
| 75 | $locale = $locale->fallback(); |
| 76 | } |
| 77 | |
| 78 | return $ids; |
| 79 | } |
| 80 | |
| 81 | protected function translateKeyword(string $keyword): string |
| 82 | { |
| 83 | return match ($keyword) { 'now' => 'NOW()' }; |
| 84 | } |
| 85 | } |