diff --git a/.gitignore b/.gitignore index cc17bd9..c298656 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,6 @@ vendor -coverage composer.lock .phpunit.cache .phpunit.result.cache .php-cs-fixer.cache -.clover.xml +clover.xml diff --git a/Bridge/Doctrine/Common/ExpressionBuilderAdapter.php.html b/Bridge/Doctrine/Common/ExpressionBuilderAdapter.php.html new file mode 100644 index 0000000..4ad8627 --- /dev/null +++ b/Bridge/Doctrine/Common/ExpressionBuilderAdapter.php.html @@ -0,0 +1,692 @@ + + +
+ ++ | Code Coverage |
+ |||||||||
+ | Lines |
+ Functions and Methods |
+ Classes and Traits |
+ |||||||
Total | +
+
+
+ |
+ 95.45% |
+ 21 / 22 |
+
+
+
+ |
+ 95.00% |
+ 19 / 20 |
+ CRAP | +
+
+
+ |
+ 0.00% |
+ 0 / 1 |
+
ExpressionBuilderAdapter | +
+
+
+ |
+ 95.45% |
+ 21 / 22 |
+
+
+
+ |
+ 95.00% |
+ 19 / 20 |
+ 21 | +
+
+
+ |
+ 0.00% |
+ 0 / 1 |
+
__construct | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
getSupportedTokenType | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
parameter | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
string | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
isNull | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
eq | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
neq | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
gt | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
gte | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
lt | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
lte | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
in | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
notIn | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
contains | +
+
+
+ |
+ 66.67% |
+ 2 / 3 |
+
+
+
+ |
+ 0.00% |
+ 0 / 1 |
+ 2.15 | ++ | ||
notContains | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
andX | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
nandX | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
orX | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
norX | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
xorX | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ |
1 | <?php |
2 | |
3 | declare(strict_types=1); |
4 | |
5 | namespace Symftony\Xpression\Bridge\Doctrine\Common; |
6 | |
7 | use Doctrine\Common\Collections\ExpressionBuilder; |
8 | use Symftony\Xpression\Exception\Expr\UnsupportedExpressionTypeException; |
9 | use Symftony\Xpression\Expr\ExpressionBuilderInterface; |
10 | use Symftony\Xpression\Lexer; |
11 | |
12 | class ExpressionBuilderAdapter implements ExpressionBuilderInterface |
13 | { |
14 | public function __construct( |
15 | private ExpressionBuilder $expressionBuilder |
16 | ) {} |
17 | |
18 | public function getSupportedTokenType(): int |
19 | { |
20 | return Lexer::T_ALL - Lexer::T_NOT_AND - Lexer::T_NOT_OR - Lexer::T_XOR - Lexer::T_NOT_DOUBLE_OPEN_CURLY_BRACKET; |
21 | } |
22 | |
23 | public function parameter(mixed $value, bool $isValue = false): mixed |
24 | { |
25 | return $value; |
26 | } |
27 | |
28 | public function string(mixed $value): mixed |
29 | { |
30 | return $value; |
31 | } |
32 | |
33 | public function isNull(string $field): mixed |
34 | { |
35 | return $this->expressionBuilder->isNull($field); |
36 | } |
37 | |
38 | public function eq(string $field, mixed $value): mixed |
39 | { |
40 | return $this->expressionBuilder->eq($field, $value); |
41 | } |
42 | |
43 | public function neq(string $field, mixed $value): mixed |
44 | { |
45 | return $this->expressionBuilder->neq($field, $value); |
46 | } |
47 | |
48 | public function gt(string $field, mixed $value): mixed |
49 | { |
50 | return $this->expressionBuilder->gt($field, $value); |
51 | } |
52 | |
53 | public function gte(string $field, mixed $value): mixed |
54 | { |
55 | return $this->expressionBuilder->gte($field, $value); |
56 | } |
57 | |
58 | public function lt(string $field, mixed $value): mixed |
59 | { |
60 | return $this->expressionBuilder->lt($field, $value); |
61 | } |
62 | |
63 | public function lte(string $field, mixed $value): mixed |
64 | { |
65 | return $this->expressionBuilder->lte($field, $value); |
66 | } |
67 | |
68 | public function in(string $field, array $values): mixed |
69 | { |
70 | return $this->expressionBuilder->in($field, $values); |
71 | } |
72 | |
73 | public function notIn(string $field, array $values): mixed |
74 | { |
75 | return $this->expressionBuilder->notIn($field, $values); |
76 | } |
77 | |
78 | /** |
79 | * /!\ Contains operator appear only in doctrine/common v1.1 /!\. |
80 | */ |
81 | public function contains(string $field, mixed $value): mixed |
82 | { |
83 | if (!method_exists($this->expressionBuilder, 'contains')) { |
84 | throw new UnsupportedExpressionTypeException('contains'); |
85 | } |
86 | |
87 | return $this->expressionBuilder->contains($field, $value); |
88 | } |
89 | |
90 | public function notContains(string $field, mixed $value): mixed |
91 | { |
92 | throw new UnsupportedExpressionTypeException('notContains'); |
93 | } |
94 | |
95 | public function andX(array $expressions): mixed |
96 | { |
97 | return $this->expressionBuilder->andX(...$expressions); |
98 | } |
99 | |
100 | public function nandX(array $expressions): mixed |
101 | { |
102 | throw new UnsupportedExpressionTypeException('nandX'); |
103 | } |
104 | |
105 | public function orX(array $expressions): mixed |
106 | { |
107 | return $this->expressionBuilder->orX(...$expressions); |
108 | } |
109 | |
110 | public function norX(array $expressions): mixed |
111 | { |
112 | throw new UnsupportedExpressionTypeException('norX'); |
113 | } |
114 | |
115 | public function xorX(array $expressions): mixed |
116 | { |
117 | throw new UnsupportedExpressionTypeException('xorX'); |
118 | } |
119 | } |
Class | +Coverage | +
---|
Class | +CRAP | +
---|
+ | Code Coverage |
+ ||||||||
+ | Lines |
+ Functions and Methods |
+ Classes and Traits |
+ ||||||
Total | +
+
+
+ |
+ 95.45% |
+ 21 / 22 |
+
+
+
+ |
+ 95.00% |
+ 19 / 20 |
+
+
+
+ |
+ 0.00% |
+ 0 / 1 |
+
ExpressionBuilderAdapter.php | +
+
+
+ |
+ 95.45% |
+ 21 / 22 |
+
+
+
+ |
+ 95.00% |
+ 19 / 20 |
+
+
+
+ |
+ 0.00% |
+ 0 / 1 |
+
+ | Code Coverage |
+ |||||||||
+ | Lines |
+ Functions and Methods |
+ Classes and Traits |
+ |||||||
Total | +
+
+
+ |
+ 100.00% |
+ 20 / 20 |
+
+
+
+ |
+ 100.00% |
+ 20 / 20 |
+ CRAP | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
ExprAdapter | +
+
+
+ |
+ 100.00% |
+ 20 / 20 |
+
+
+
+ |
+ 100.00% |
+ 20 / 20 |
+ 21 | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
__construct | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
getSupportedTokenType | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
parameter | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 2 | ++ | ||
string | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
isNull | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
eq | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
neq | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
gt | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
gte | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
lt | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
lte | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
in | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
notIn | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
contains | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
notContains | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
andX | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
nandX | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
orX | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
norX | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
xorX | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ |
1 | <?php |
2 | |
3 | declare(strict_types=1); |
4 | |
5 | namespace Symftony\Xpression\Bridge\Doctrine\ORM; |
6 | |
7 | use Doctrine\ORM\Query\Expr; |
8 | use Symftony\Xpression\Exception\Expr\UnsupportedExpressionTypeException; |
9 | use Symftony\Xpression\Expr\ExpressionBuilderInterface; |
10 | use Symftony\Xpression\Lexer; |
11 | |
12 | class ExprAdapter implements ExpressionBuilderInterface |
13 | { |
14 | private Expr $expr; |
15 | |
16 | public function __construct(Expr $expr) |
17 | { |
18 | $this->expr = $expr; |
19 | } |
20 | |
21 | public function getSupportedTokenType(): int |
22 | { |
23 | return Lexer::T_ALL - Lexer::T_NOT_AND - Lexer::T_NOT_OR - Lexer::T_XOR; |
24 | } |
25 | |
26 | public function parameter(mixed $value, bool $isValue = false): mixed |
27 | { |
28 | return $isValue ? $this->expr->literal($value) : $value; |
29 | } |
30 | |
31 | public function string(mixed $value): mixed |
32 | { |
33 | return $this->expr->literal($value); |
34 | } |
35 | |
36 | public function isNull(string $field): mixed |
37 | { |
38 | return $this->expr->isNull($field); |
39 | } |
40 | |
41 | public function eq(string $field, mixed $value): mixed |
42 | { |
43 | return $this->expr->eq($field, $value); |
44 | } |
45 | |
46 | public function neq(string $field, mixed $value): mixed |
47 | { |
48 | return $this->expr->neq($field, $value); |
49 | } |
50 | |
51 | public function gt(string $field, mixed $value): mixed |
52 | { |
53 | return $this->expr->gt($field, $value); |
54 | } |
55 | |
56 | public function gte(string $field, mixed $value): mixed |
57 | { |
58 | return $this->expr->gte($field, $value); |
59 | } |
60 | |
61 | public function lt(string $field, mixed $value): mixed |
62 | { |
63 | return $this->expr->lt($field, $value); |
64 | } |
65 | |
66 | public function lte(string $field, mixed $value): mixed |
67 | { |
68 | return $this->expr->lte($field, $value); |
69 | } |
70 | |
71 | public function in(string $field, array $values): mixed |
72 | { |
73 | return $this->expr->in($field, $values); |
74 | } |
75 | |
76 | public function notIn(string $field, array $values): mixed |
77 | { |
78 | return $this->expr->notIn($field, $values); |
79 | } |
80 | |
81 | public function contains(string $field, mixed $value): mixed |
82 | { |
83 | return $this->expr->like($field, $value); |
84 | } |
85 | |
86 | public function notContains(string $field, mixed $value): mixed |
87 | { |
88 | return $this->expr->notLike($field, $value); |
89 | } |
90 | |
91 | public function andX(array $expressions): mixed |
92 | { |
93 | return $this->expr->andX(...$expressions); |
94 | } |
95 | |
96 | public function nandX(array $expressions): mixed |
97 | { |
98 | throw new UnsupportedExpressionTypeException('nandX'); |
99 | } |
100 | |
101 | public function orX(array $expressions): mixed |
102 | { |
103 | return $this->expr->orX(...$expressions); |
104 | } |
105 | |
106 | public function norX(array $expressions): mixed |
107 | { |
108 | throw new UnsupportedExpressionTypeException('norX'); |
109 | } |
110 | |
111 | public function xorX(array $expressions): mixed |
112 | { |
113 | throw new UnsupportedExpressionTypeException('xorX'); |
114 | } |
115 | } |
Class | +Coverage | +
---|
Class | +CRAP | +
---|
Method | +Coverage | +
---|
Method | +CRAP | +
---|
+ | Code Coverage |
+ ||||||||
+ | Lines |
+ Functions and Methods |
+ Classes and Traits |
+ ||||||
Total | +
+
+
+ |
+ 100.00% |
+ 20 / 20 |
+
+
+
+ |
+ 100.00% |
+ 20 / 20 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
ExprAdapter.php | +
+
+
+ |
+ 100.00% |
+ 20 / 20 |
+
+
+
+ |
+ 100.00% |
+ 20 / 20 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
Class | +Coverage | +
---|
Class | +CRAP | +
---|
+ | Code Coverage |
+ ||||||||
+ | Lines |
+ Functions and Methods |
+ Classes and Traits |
+ ||||||
Total | +
+
+
+ |
+ 97.62% |
+ 41 / 42 |
+
+
+
+ |
+ 97.50% |
+ 39 / 40 |
+
+
+
+ |
+ 50.00% |
+ 1 / 2 |
+
Common | +
+
+
+ |
+ 95.45% |
+ 21 / 22 |
+
+
+
+ |
+ 95.00% |
+ 19 / 20 |
+
+
+
+ |
+ 0.00% |
+ 0 / 1 |
+
ORM | +
+
+
+ |
+ 100.00% |
+ 20 / 20 |
+
+
+
+ |
+ 100.00% |
+ 20 / 20 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+ | Code Coverage |
+ |||||||||
+ | Lines |
+ Functions and Methods |
+ Classes and Traits |
+ |||||||
Total | +
+
+
+ |
+ 100.00% |
+ 19 / 19 |
+
+
+
+ |
+ 100.00% |
+ 19 / 19 |
+ CRAP | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
ExprBuilder | +
+
+
+ |
+ 100.00% |
+ 19 / 19 |
+
+
+
+ |
+ 100.00% |
+ 19 / 19 |
+ 19 | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
getSupportedTokenType | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
parameter | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
string | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
isNull | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
eq | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
neq | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
gt | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
gte | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
lt | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
lte | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
in | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
notIn | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
contains | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
notContains | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
andX | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
nandX | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
orX | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
norX | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
xorX | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ |
1 | <?php |
2 | |
3 | declare(strict_types=1); |
4 | |
5 | namespace Symftony\Xpression\Bridge\MongoDB; |
6 | |
7 | use Symftony\Xpression\Exception\Expr\UnsupportedExpressionTypeException; |
8 | use Symftony\Xpression\Expr\ExpressionBuilderInterface; |
9 | use Symftony\Xpression\Lexer; |
10 | |
11 | class ExprBuilder implements ExpressionBuilderInterface |
12 | { |
13 | public function getSupportedTokenType(): int |
14 | { |
15 | return Lexer::T_ALL - Lexer::T_XOR; |
16 | } |
17 | |
18 | public function parameter(mixed $value, bool $isValue = false): mixed |
19 | { |
20 | return $value; |
21 | } |
22 | |
23 | public function string(mixed $value): mixed |
24 | { |
25 | return $value; |
26 | } |
27 | |
28 | public function isNull(string $field): mixed |
29 | { |
30 | return [$field => null]; |
31 | } |
32 | |
33 | public function eq(string $field, mixed $value): mixed |
34 | { |
35 | return [$field => ['$eq' => $value]]; |
36 | } |
37 | |
38 | public function neq(string $field, mixed $value): mixed |
39 | { |
40 | return [$field => ['$ne' => $value]]; |
41 | } |
42 | |
43 | public function gt(string $field, mixed $value): mixed |
44 | { |
45 | return [$field => ['$gt' => $value]]; |
46 | } |
47 | |
48 | public function gte(string $field, mixed $value): mixed |
49 | { |
50 | return [$field => ['$gte' => $value]]; |
51 | } |
52 | |
53 | public function lt(string $field, mixed $value): mixed |
54 | { |
55 | return [$field => ['$lt' => $value]]; |
56 | } |
57 | |
58 | public function lte(string $field, mixed $value): mixed |
59 | { |
60 | return [$field => ['$lte' => $value]]; |
61 | } |
62 | |
63 | public function in(string $field, array $values): mixed |
64 | { |
65 | return [$field => ['$in' => $values]]; |
66 | } |
67 | |
68 | public function notIn(string $field, array $values): mixed |
69 | { |
70 | return [$field => ['$nin' => $values]]; |
71 | } |
72 | |
73 | public function contains(string $field, mixed $value): mixed |
74 | { |
75 | return [$field => ['$regex' => $value]]; |
76 | } |
77 | |
78 | public function notContains(string $field, mixed $value): mixed |
79 | { |
80 | return ['$not' => $this->contains($field, $value)]; |
81 | } |
82 | |
83 | public function andX(array $expressions): mixed |
84 | { |
85 | return ['$and' => $expressions]; |
86 | } |
87 | |
88 | // Not A AND B = Not A OR Not B |
89 | public function nandX(array $expressions): mixed |
90 | { |
91 | return $this->orX(array_map(static fn ($expression) => ['$not' => $expression], $expressions)); |
92 | } |
93 | |
94 | public function orX(array $expressions): mixed |
95 | { |
96 | return ['$or' => $expressions]; |
97 | } |
98 | |
99 | public function norX(array $expressions): mixed |
100 | { |
101 | return ['$nor' => $expressions]; |
102 | } |
103 | |
104 | public function xorX(array $expressions): mixed |
105 | { |
106 | throw new UnsupportedExpressionTypeException('xorX'); |
107 | } |
108 | } |
Class | +Coverage | +
---|
Class | +CRAP | +
---|
Method | +Coverage | +
---|
Method | +CRAP | +
---|
+ | Code Coverage |
+ ||||||||
+ | Lines |
+ Functions and Methods |
+ Classes and Traits |
+ ||||||
Total | +
+
+
+ |
+ 100.00% |
+ 19 / 19 |
+
+
+
+ |
+ 100.00% |
+ 19 / 19 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
ExprBuilder.php | +
+
+
+ |
+ 100.00% |
+ 19 / 19 |
+
+
+
+ |
+ 100.00% |
+ 19 / 19 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
Class | +Coverage | +
---|
Class | +CRAP | +
---|
+ | Code Coverage |
+ ||||||||
+ | Lines |
+ Functions and Methods |
+ Classes and Traits |
+ ||||||
Total | +
+
+
+ |
+ 98.36% |
+ 60 / 61 |
+
+
+
+ |
+ 98.31% |
+ 58 / 59 |
+
+
+
+ |
+ 66.67% |
+ 2 / 3 |
+
Doctrine | +
+
+
+ |
+ 97.62% |
+ 41 / 42 |
+
+
+
+ |
+ 97.50% |
+ 39 / 40 |
+
+
+
+ |
+ 50.00% |
+ 1 / 2 |
+
MongoDB | +
+
+
+ |
+ 100.00% |
+ 19 / 19 |
+
+
+
+ |
+ 100.00% |
+ 19 / 19 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+ | Code Coverage |
+ |||||||||
+ | Lines |
+ Functions and Methods |
+ Classes and Traits |
+ |||||||
Total | +
+
+
+ |
+ 96.67% |
+ 58 / 60 |
+
+
+
+ |
+ 95.00% |
+ 19 / 20 |
+ CRAP | +
+
+
+ |
+ 0.00% |
+ 0 / 1 |
+
ClosureExpressionBuilder | +
+
+
+ |
+ 96.67% |
+ 58 / 60 |
+
+
+
+ |
+ 95.00% |
+ 19 / 20 |
+ 34 | +
+
+
+ |
+ 0.00% |
+ 0 / 1 |
+
getObjectFieldValue | +
+
+
+ |
+ 90.91% |
+ 20 / 22 |
+
+
+
+ |
+ 0.00% |
+ 0 / 1 |
+ 9.06 | ++ | ||
getSupportedTokenType | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
parameter | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
string | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
isNull | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
eq | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
neq | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
gt | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
gte | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
lt | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
lte | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
in | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
notIn | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
contains | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
notContains | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
andX | +
+
+
+ |
+ 100.00% |
+ 6 / 6 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 3 | ++ | ||
nandX | +
+
+
+ |
+ 100.00% |
+ 2 / 2 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
orX | +
+
+
+ |
+ 100.00% |
+ 6 / 6 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 3 | ++ | ||
norX | +
+
+
+ |
+ 100.00% |
+ 2 / 2 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
xorX | +
+
+
+ |
+ 100.00% |
+ 8 / 8 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 3 | ++ |
1 | <?php |
2 | |
3 | declare(strict_types=1); |
4 | |
5 | namespace Symftony\Xpression\Expr; |
6 | |
7 | use Symftony\Xpression\Lexer; |
8 | |
9 | class ClosureExpressionBuilder implements ExpressionBuilderInterface |
10 | { |
11 | public static function getObjectFieldValue(mixed $object, mixed $field): mixed |
12 | { |
13 | if (\is_array($object)) { |
14 | return $object[$field]; |
15 | } |
16 | |
17 | $accessors = ['get', 'is']; |
18 | |
19 | foreach ($accessors as $accessor) { |
20 | $accessor .= $field; |
21 | |
22 | if (!method_exists($object, $accessor)) { |
23 | continue; |
24 | } |
25 | |
26 | return $object->{$accessor}(); |
27 | } |
28 | |
29 | // __call should be triggered for get. |
30 | $accessor = $accessors[0].$field; |
31 | |
32 | if (method_exists($object, '__call')) { |
33 | return $object->{$accessor}(); |
34 | } |
35 | |
36 | if ($object instanceof \ArrayAccess) { |
37 | return $object[$field]; |
38 | } |
39 | |
40 | if (isset($object->{$field})) { |
41 | return $object->{$field}; |
42 | } |
43 | |
44 | // camelcase field name to support different variable naming conventions |
45 | $ccField = preg_replace_callback('/_(.?)/', static fn ($matches) => strtoupper($matches[1]), $field); |
46 | |
47 | foreach ($accessors as $accessor) { |
48 | $accessor .= $ccField; |
49 | |
50 | if (!method_exists($object, $accessor)) { |
51 | continue; |
52 | } |
53 | |
54 | return $object->{$accessor}(); |
55 | } |
56 | |
57 | return $object->{$field}; |
58 | } |
59 | |
60 | public function getSupportedTokenType(): int |
61 | { |
62 | return Lexer::T_ALL; |
63 | } |
64 | |
65 | /** |
66 | * @param bool $isValue |
67 | * @param mixed $value |
68 | */ |
69 | public function parameter($value, $isValue = false): mixed |
70 | { |
71 | return $value; |
72 | } |
73 | |
74 | public function string(mixed $value): mixed |
75 | { |
76 | return $value; |
77 | } |
78 | |
79 | public function isNull(string $field): mixed |
80 | { |
81 | return static fn ($object) => null === ClosureExpressionBuilder::getObjectFieldValue($object, $field); |
82 | } |
83 | |
84 | public function eq(string $field, mixed $value): mixed |
85 | { |
86 | return static fn ($object) => ClosureExpressionBuilder::getObjectFieldValue($object, $field) === $value; |
87 | } |
88 | |
89 | public function neq(string $field, mixed $value): mixed |
90 | { |
91 | return static fn ($object) => ClosureExpressionBuilder::getObjectFieldValue($object, $field) !== $value; |
92 | } |
93 | |
94 | public function gt(string $field, mixed $value): mixed |
95 | { |
96 | return static fn ($object) => ClosureExpressionBuilder::getObjectFieldValue($object, $field) > $value; |
97 | } |
98 | |
99 | public function gte(string $field, mixed $value): mixed |
100 | { |
101 | return static fn ($object) => ClosureExpressionBuilder::getObjectFieldValue($object, $field) >= $value; |
102 | } |
103 | |
104 | public function lt(string $field, mixed $value): mixed |
105 | { |
106 | return static fn ($object) => ClosureExpressionBuilder::getObjectFieldValue($object, $field) < $value; |
107 | } |
108 | |
109 | public function lte(string $field, mixed $value): mixed |
110 | { |
111 | return static fn ($object) => ClosureExpressionBuilder::getObjectFieldValue($object, $field) <= $value; |
112 | } |
113 | |
114 | public function in(string $field, array $values): mixed |
115 | { |
116 | return static fn ($object) => \in_array(ClosureExpressionBuilder::getObjectFieldValue($object, $field), $values, true); |
117 | } |
118 | |
119 | public function notIn(string $field, array $values): mixed |
120 | { |
121 | return static fn ($object) => !\in_array(ClosureExpressionBuilder::getObjectFieldValue($object, $field), $values, true); |
122 | } |
123 | |
124 | public function contains(string $field, mixed $value): mixed |
125 | { |
126 | return static fn ($object) => str_contains(ClosureExpressionBuilder::getObjectFieldValue($object, $field), $value); |
127 | } |
128 | |
129 | public function notContains(string $field, mixed $value): mixed |
130 | { |
131 | return static fn ($object) => !str_contains(ClosureExpressionBuilder::getObjectFieldValue($object, $field), $value); |
132 | } |
133 | |
134 | public function andX(array $expressions): mixed |
135 | { |
136 | return static function ($object) use ($expressions) { |
137 | foreach ($expressions as $expression) { |
138 | if (!$expression($object)) { |
139 | return false; |
140 | } |
141 | } |
142 | |
143 | return true; |
144 | }; |
145 | } |
146 | |
147 | public function nandX(array $expressions): mixed |
148 | { |
149 | $self = $this; |
150 | |
151 | return static fn ($object) => !$self->andX($expressions)($object); |
152 | } |
153 | |
154 | public function orX(array $expressions): mixed |
155 | { |
156 | return static function ($object) use ($expressions) { |
157 | foreach ($expressions as $expression) { |
158 | if ($expression($object)) { |
159 | return true; |
160 | } |
161 | } |
162 | |
163 | return false; |
164 | }; |
165 | } |
166 | |
167 | public function norX(array $expressions): mixed |
168 | { |
169 | $self = $this; |
170 | |
171 | return static fn ($object) => !$self->orX($expressions)($object); |
172 | } |
173 | |
174 | public function xorX(array $expressions): mixed |
175 | { |
176 | return static function ($object) use ($expressions) { |
177 | $result = 0; |
178 | foreach ($expressions as $expression) { |
179 | if ($expression($object)) { |
180 | ++$result; |
181 | } |
182 | } |
183 | |
184 | $countExpressions = \count($expressions); |
185 | |
186 | return 1 === $result | (2 < $countExpressions & $result === $countExpressions); |
187 | }; |
188 | } |
189 | } |
+ | Code Coverage |
+ |||||||||
+ | Lines |
+ Functions and Methods |
+ Classes and Traits |
+ |||||||
Total | ++ | n/a |
+ 0 / 0 |
+ + | n/a |
+ 0 / 0 |
+ CRAP | ++ | n/a |
+ 0 / 0 |
+
1 | <?php |
2 | |
3 | declare(strict_types=1); |
4 | |
5 | namespace Symftony\Xpression\Expr; |
6 | |
7 | interface ExpressionBuilderInterface |
8 | { |
9 | /** |
10 | * Must return all supported token type. |
11 | */ |
12 | public function getSupportedTokenType(): int; |
13 | |
14 | public function parameter(mixed $value, bool $isValue = false): mixed; |
15 | |
16 | public function string(mixed $value): mixed; |
17 | |
18 | public function isNull(string $field): mixed; |
19 | |
20 | public function eq(string $field, mixed $value): mixed; |
21 | |
22 | public function neq(string $field, mixed $value): mixed; |
23 | |
24 | public function gt(string $field, mixed $value): mixed; |
25 | |
26 | public function gte(string $field, mixed $value): mixed; |
27 | |
28 | public function lt(string $field, mixed $value): mixed; |
29 | |
30 | public function lte(string $field, mixed $value): mixed; |
31 | |
32 | public function in(string $field, array $values): mixed; |
33 | |
34 | public function notIn(string $field, array $values): mixed; |
35 | |
36 | public function contains(string $field, mixed $value): mixed; |
37 | |
38 | public function notContains(string $field, mixed $value): mixed; |
39 | |
40 | public function andX(array $expressions): mixed; |
41 | |
42 | public function nandX(array $expressions): mixed; |
43 | |
44 | public function orX(array $expressions): mixed; |
45 | |
46 | public function norX(array $expressions): mixed; |
47 | |
48 | public function xorX(array $expressions): mixed; |
49 | } |
+ | Code Coverage |
+ |||||||||
+ | Lines |
+ Functions and Methods |
+ Classes and Traits |
+ |||||||
Total | +
+
+
+ |
+ 100.00% |
+ 25 / 25 |
+
+
+
+ |
+ 100.00% |
+ 20 / 20 |
+ CRAP | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
HtmlExpressionBuilder | +
+
+
+ |
+ 100.00% |
+ 25 / 25 |
+
+
+
+ |
+ 100.00% |
+ 20 / 20 |
+ 22 | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
__construct | +
+
+
+ |
+ 100.00% |
+ 6 / 6 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 3 | ++ | ||
getSupportedTokenType | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
parameter | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
string | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
isNull | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
eq | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
neq | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
gt | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
gte | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
lt | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
lte | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
in | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
notIn | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
contains | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
notContains | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
andX | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
nandX | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
orX | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
norX | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
xorX | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ |
1 | <?php |
2 | |
3 | declare(strict_types=1); |
4 | |
5 | namespace Symftony\Xpression\Expr; |
6 | |
7 | use Symftony\Xpression\Lexer; |
8 | |
9 | class HtmlExpressionBuilder implements ExpressionBuilderInterface |
10 | { |
11 | /** |
12 | * This callable is use to delegate the html generation to a third party |
13 | * eg: $comparisonHtmlBuilder($field, $operator, $value) |
14 | * it must return the html code. |
15 | * |
16 | * @var callable |
17 | */ |
18 | private $comparisonHtmlBuilder; |
19 | |
20 | /** |
21 | * This callable is use to delegate the html generation to a third party |
22 | * eg: $compositeHtmlBuilder(array $expressions, $type) |
23 | * it must return the html code. |
24 | * |
25 | * @var callable |
26 | */ |
27 | private $compositeHtmlBuilder; |
28 | |
29 | public function __construct(callable $comparisonHtmlBuilder = null, callable $compositeHtmlBuilder = null) |
30 | { |
31 | $this->comparisonHtmlBuilder = $comparisonHtmlBuilder ?: static fn ($field, $operator, $value) => sprintf('<div>%s %s %s</div>', $field, $operator, $value); |
32 | $this->compositeHtmlBuilder = $compositeHtmlBuilder ?: static fn (array $expressions, $type) => str_replace( |
33 | ['{type}', '{expressions}'], |
34 | [$type, implode('', $expressions)], |
35 | '<fieldset><legend>{type}</legend>{expressions}</fieldset>' |
36 | ); |
37 | } |
38 | |
39 | public function getSupportedTokenType(): int |
40 | { |
41 | return Lexer::T_ALL; |
42 | } |
43 | |
44 | public function parameter(mixed $value, bool $isValue = false): mixed |
45 | { |
46 | return $value; |
47 | } |
48 | |
49 | public function string(mixed $value): mixed |
50 | { |
51 | return '"'.$value.'"'; |
52 | } |
53 | |
54 | public function isNull(string $field): mixed |
55 | { |
56 | return ($this->comparisonHtmlBuilder)($field, 'is', 'null'); |
57 | } |
58 | |
59 | public function eq(string $field, mixed $value): mixed |
60 | { |
61 | return ($this->comparisonHtmlBuilder)($field, '=', $value); |
62 | } |
63 | |
64 | public function neq(string $field, mixed $value): mixed |
65 | { |
66 | return ($this->comparisonHtmlBuilder)($field, '≠', $value); |
67 | } |
68 | |
69 | public function gt(string $field, mixed $value): mixed |
70 | { |
71 | return ($this->comparisonHtmlBuilder)($field, '>', $value); |
72 | } |
73 | |
74 | public function gte(string $field, mixed $value): mixed |
75 | { |
76 | return ($this->comparisonHtmlBuilder)($field, '≥', $value); |
77 | } |
78 | |
79 | public function lt(string $field, mixed $value): mixed |
80 | { |
81 | return ($this->comparisonHtmlBuilder)($field, '<', $value); |
82 | } |
83 | |
84 | public function lte(string $field, mixed $value): mixed |
85 | { |
86 | return ($this->comparisonHtmlBuilder)($field, '≤', $value); |
87 | } |
88 | |
89 | public function in(string $field, array $values): mixed |
90 | { |
91 | return ($this->comparisonHtmlBuilder)($field, 'value in', implode(', ', $values)); |
92 | } |
93 | |
94 | public function notIn(string $field, array $values): mixed |
95 | { |
96 | return ($this->comparisonHtmlBuilder)($field, 'value not in', implode(', ', $values)); |
97 | } |
98 | |
99 | public function contains(string $field, mixed $value): mixed |
100 | { |
101 | return ($this->comparisonHtmlBuilder)($field, 'contains', $value); |
102 | } |
103 | |
104 | public function notContains(string $field, mixed $value): mixed |
105 | { |
106 | return ($this->comparisonHtmlBuilder)($field, 'notContains', $value); |
107 | } |
108 | |
109 | public function andX(array $expressions): mixed |
110 | { |
111 | return ($this->compositeHtmlBuilder)($expressions, 'and'); |
112 | } |
113 | |
114 | public function nandX(array $expressions): mixed |
115 | { |
116 | return ($this->compositeHtmlBuilder)($expressions, 'not-and'); |
117 | } |
118 | |
119 | public function orX(array $expressions): mixed |
120 | { |
121 | return ($this->compositeHtmlBuilder)($expressions, 'or'); |
122 | } |
123 | |
124 | public function norX(array $expressions): mixed |
125 | { |
126 | return ($this->compositeHtmlBuilder)($expressions, 'not-or'); |
127 | } |
128 | |
129 | public function xorX(array $expressions): mixed |
130 | { |
131 | return ($this->compositeHtmlBuilder)($expressions, 'exclusive-or'); |
132 | } |
133 | } |
+ | Code Coverage |
+ |||||||||
+ | Lines |
+ Functions and Methods |
+ Classes and Traits |
+ |||||||
Total | +
+
+
+ |
+ 96.43% |
+ 27 / 28 |
+
+
+
+ |
+ 95.24% |
+ 20 / 21 |
+ CRAP | +
+
+
+ |
+ 0.00% |
+ 0 / 1 |
+
MapperExpressionBuilder | +
+
+
+ |
+ 96.43% |
+ 27 / 28 |
+
+
+
+ |
+ 95.24% |
+ 20 / 21 |
+ 26 | +
+
+
+ |
+ 0.00% |
+ 0 / 1 |
+
__construct | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
getSupportedTokenType | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
parameter | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
string | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
isNull | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
eq | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
neq | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
gt | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
gte | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
lt | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
lte | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
in | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
notIn | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
contains | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
notContains | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
andX | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
nandX | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
orX | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
norX | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
xorX | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
mapField | +
+
+
+ |
+ 87.50% |
+ 7 / 8 |
+
+
+
+ |
+ 0.00% |
+ 0 / 1 |
+ 6.07 | ++ |
1 | <?php |
2 | |
3 | declare(strict_types=1); |
4 | |
5 | namespace Symftony\Xpression\Expr; |
6 | |
7 | class MapperExpressionBuilder implements ExpressionBuilderInterface |
8 | { |
9 | /** |
10 | * @param string[] $fieldMapping |
11 | */ |
12 | public function __construct( |
13 | private ExpressionBuilderInterface $expressionBuilder, |
14 | private array $fieldMapping = [], |
15 | ) {} |
16 | |
17 | public function getSupportedTokenType(): int |
18 | { |
19 | return $this->expressionBuilder->getSupportedTokenType(); |
20 | } |
21 | |
22 | public function parameter(mixed $value, bool $isValue = false): mixed |
23 | { |
24 | return $this->expressionBuilder->parameter($value, $isValue); |
25 | } |
26 | |
27 | public function string(mixed $value): mixed |
28 | { |
29 | return $this->expressionBuilder->string($value); |
30 | } |
31 | |
32 | public function isNull(string $field): mixed |
33 | { |
34 | return $this->expressionBuilder->isNull($this->mapField($field)); |
35 | } |
36 | |
37 | public function eq(string $field, mixed $value): mixed |
38 | { |
39 | return $this->expressionBuilder->eq($this->mapField($field), $value); |
40 | } |
41 | |
42 | public function neq(string $field, mixed $value): mixed |
43 | { |
44 | return $this->expressionBuilder->neq($this->mapField($field), $value); |
45 | } |
46 | |
47 | public function gt(string $field, mixed $value): mixed |
48 | { |
49 | return $this->expressionBuilder->gt($this->mapField($field), $value); |
50 | } |
51 | |
52 | public function gte(string $field, mixed $value): mixed |
53 | { |
54 | return $this->expressionBuilder->gte($this->mapField($field), $value); |
55 | } |
56 | |
57 | public function lt(string $field, mixed $value): mixed |
58 | { |
59 | return $this->expressionBuilder->lt($this->mapField($field), $value); |
60 | } |
61 | |
62 | public function lte(string $field, mixed $value): mixed |
63 | { |
64 | return $this->expressionBuilder->lte($this->mapField($field), $value); |
65 | } |
66 | |
67 | public function in(string $field, array $values): mixed |
68 | { |
69 | return $this->expressionBuilder->in($this->mapField($field), $values); |
70 | } |
71 | |
72 | public function notIn(string $field, array $values): mixed |
73 | { |
74 | return $this->expressionBuilder->notIn($this->mapField($field), $values); |
75 | } |
76 | |
77 | public function contains(string $field, mixed $value): mixed |
78 | { |
79 | return $this->expressionBuilder->contains($this->mapField($field), $value); |
80 | } |
81 | |
82 | public function notContains(string $field, mixed $value): mixed |
83 | { |
84 | return $this->expressionBuilder->notContains($this->mapField($field), $value); |
85 | } |
86 | |
87 | public function andX(array $expressions): mixed |
88 | { |
89 | return $this->expressionBuilder->andX($expressions); |
90 | } |
91 | |
92 | public function nandX(array $expressions): mixed |
93 | { |
94 | return $this->expressionBuilder->nandX($expressions); |
95 | } |
96 | |
97 | public function orX(array $expressions): mixed |
98 | { |
99 | return $this->expressionBuilder->orX($expressions); |
100 | } |
101 | |
102 | public function norX(array $expressions): mixed |
103 | { |
104 | return $this->expressionBuilder->norX($expressions); |
105 | } |
106 | |
107 | public function xorX(array $expressions): mixed |
108 | { |
109 | return $this->expressionBuilder->xorX($expressions); |
110 | } |
111 | |
112 | private function mapField(mixed $field): mixed |
113 | { |
114 | if ( |
115 | \is_array($field) |
116 | || \is_object($field) && !method_exists($field, '__toString') |
117 | ) { |
118 | return $field; |
119 | } |
120 | |
121 | if (\array_key_exists((string) $field, $this->fieldMapping)) { |
122 | return sprintf($this->fieldMapping[(string) $field], $field); |
123 | } |
124 | |
125 | if (\array_key_exists('*', $this->fieldMapping)) { |
126 | return sprintf($this->fieldMapping['*'], $field); |
127 | } |
128 | |
129 | return $field; |
130 | } |
131 | } |
Class | +Coverage | +
---|
Class | +CRAP | +
---|
+ | Code Coverage |
+ ||||||||
+ | Lines |
+ Functions and Methods |
+ Classes and Traits |
+ ||||||
Total | +
+
+
+ |
+ 97.35% |
+ 110 / 113 |
+
+
+
+ |
+ 96.72% |
+ 59 / 61 |
+
+
+
+ |
+ 33.33% |
+ 1 / 3 |
+
ClosureExpressionBuilder.php | +
+
+
+ |
+ 96.67% |
+ 58 / 60 |
+
+
+
+ |
+ 95.00% |
+ 19 / 20 |
+
+
+
+ |
+ 0.00% |
+ 0 / 1 |
+
ExpressionBuilderInterface.php | ++ | n/a |
+ 0 / 0 |
+ + | n/a |
+ 0 / 0 |
+ + | n/a |
+ 0 / 0 |
+
HtmlExpressionBuilder.php | +
+
+
+ |
+ 100.00% |
+ 25 / 25 |
+
+
+
+ |
+ 100.00% |
+ 20 / 20 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
MapperExpressionBuilder.php | +
+
+
+ |
+ 96.43% |
+ 27 / 28 |
+
+
+
+ |
+ 95.24% |
+ 20 / 21 |
+
+
+
+ |
+ 0.00% |
+ 0 / 1 |
+
+ | Code Coverage |
+ |||||||||
+ | Lines |
+ Functions and Methods |
+ Classes and Traits |
+ |||||||
Total | +
+
+
+ |
+ 95.45% |
+ 21 / 22 |
+
+
+
+ |
+ 95.00% |
+ 19 / 20 |
+ CRAP | +
+
+
+ |
+ 0.00% |
+ 0 / 1 |
+
ExpressionBuilderAdapter | +
+
+
+ |
+ 95.45% |
+ 21 / 22 |
+
+
+
+ |
+ 95.00% |
+ 19 / 20 |
+ 21 | +
+
+
+ |
+ 0.00% |
+ 0 / 1 |
+
__construct | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
getSupportedTokenType | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
parameter | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
string | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
isNull | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
eq | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
neq | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
gt | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
gte | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
lt | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
lte | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
in | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
notIn | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
contains | +
+
+
+ |
+ 66.67% |
+ 2 / 3 |
+
+
+
+ |
+ 0.00% |
+ 0 / 1 |
+ 2.15 | ++ | ||
notContains | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
andX | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
nandX | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
orX | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
norX | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
xorX | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ |
1 | <?php |
2 | |
3 | declare(strict_types=1); |
4 | |
5 | namespace Symftony\Xpression\Bridge\Doctrine\Common; |
6 | |
7 | use Doctrine\Common\Collections\ExpressionBuilder; |
8 | use Symftony\Xpression\Exception\Expr\UnsupportedExpressionTypeException; |
9 | use Symftony\Xpression\Expr\ExpressionBuilderInterface; |
10 | use Symftony\Xpression\Lexer; |
11 | |
12 | class ExpressionBuilderAdapter implements ExpressionBuilderInterface |
13 | { |
14 | public function __construct( |
15 | private ExpressionBuilder $expressionBuilder |
16 | ) {} |
17 | |
18 | public function getSupportedTokenType(): int |
19 | { |
20 | return Lexer::T_ALL - Lexer::T_NOT_AND - Lexer::T_NOT_OR - Lexer::T_XOR - Lexer::T_NOT_DOUBLE_OPEN_CURLY_BRACKET; |
21 | } |
22 | |
23 | public function parameter(mixed $value, bool $isValue = false): mixed |
24 | { |
25 | return $value; |
26 | } |
27 | |
28 | public function string(mixed $value): mixed |
29 | { |
30 | return $value; |
31 | } |
32 | |
33 | public function isNull(string $field): mixed |
34 | { |
35 | return $this->expressionBuilder->isNull($field); |
36 | } |
37 | |
38 | public function eq(string $field, mixed $value): mixed |
39 | { |
40 | return $this->expressionBuilder->eq($field, $value); |
41 | } |
42 | |
43 | public function neq(string $field, mixed $value): mixed |
44 | { |
45 | return $this->expressionBuilder->neq($field, $value); |
46 | } |
47 | |
48 | public function gt(string $field, mixed $value): mixed |
49 | { |
50 | return $this->expressionBuilder->gt($field, $value); |
51 | } |
52 | |
53 | public function gte(string $field, mixed $value): mixed |
54 | { |
55 | return $this->expressionBuilder->gte($field, $value); |
56 | } |
57 | |
58 | public function lt(string $field, mixed $value): mixed |
59 | { |
60 | return $this->expressionBuilder->lt($field, $value); |
61 | } |
62 | |
63 | public function lte(string $field, mixed $value): mixed |
64 | { |
65 | return $this->expressionBuilder->lte($field, $value); |
66 | } |
67 | |
68 | public function in(string $field, array $values): mixed |
69 | { |
70 | return $this->expressionBuilder->in($field, $values); |
71 | } |
72 | |
73 | public function notIn(string $field, array $values): mixed |
74 | { |
75 | return $this->expressionBuilder->notIn($field, $values); |
76 | } |
77 | |
78 | /** |
79 | * /!\ Contains operator appear only in doctrine/common v1.1 /!\. |
80 | */ |
81 | public function contains(string $field, mixed $value): mixed |
82 | { |
83 | if (!method_exists($this->expressionBuilder, 'contains')) { |
84 | throw new UnsupportedExpressionTypeException('contains'); |
85 | } |
86 | |
87 | return $this->expressionBuilder->contains($field, $value); |
88 | } |
89 | |
90 | public function notContains(string $field, mixed $value): mixed |
91 | { |
92 | throw new UnsupportedExpressionTypeException('notContains'); |
93 | } |
94 | |
95 | public function andX(array $expressions): mixed |
96 | { |
97 | return $this->expressionBuilder->andX(...$expressions); |
98 | } |
99 | |
100 | public function nandX(array $expressions): mixed |
101 | { |
102 | throw new UnsupportedExpressionTypeException('nandX'); |
103 | } |
104 | |
105 | public function orX(array $expressions): mixed |
106 | { |
107 | return $this->expressionBuilder->orX(...$expressions); |
108 | } |
109 | |
110 | public function norX(array $expressions): mixed |
111 | { |
112 | throw new UnsupportedExpressionTypeException('norX'); |
113 | } |
114 | |
115 | public function xorX(array $expressions): mixed |
116 | { |
117 | throw new UnsupportedExpressionTypeException('xorX'); |
118 | } |
119 | } |
Class | +Coverage | +
---|
Class | +CRAP | +
---|
+ | Code Coverage |
+ ||||||||
+ | Lines |
+ Functions and Methods |
+ Classes and Traits |
+ ||||||
Total | +
+
+
+ |
+ 95.45% |
+ 21 / 22 |
+
+
+
+ |
+ 95.00% |
+ 19 / 20 |
+
+
+
+ |
+ 0.00% |
+ 0 / 1 |
+
ExpressionBuilderAdapter.php | +
+
+
+ |
+ 95.45% |
+ 21 / 22 |
+
+
+
+ |
+ 95.00% |
+ 19 / 20 |
+
+
+
+ |
+ 0.00% |
+ 0 / 1 |
+
+ | Code Coverage |
+ |||||||||
+ | Lines |
+ Functions and Methods |
+ Classes and Traits |
+ |||||||
Total | +
+
+
+ |
+ 100.00% |
+ 20 / 20 |
+
+
+
+ |
+ 100.00% |
+ 20 / 20 |
+ CRAP | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
ExprAdapter | +
+
+
+ |
+ 100.00% |
+ 20 / 20 |
+
+
+
+ |
+ 100.00% |
+ 20 / 20 |
+ 21 | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
__construct | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
getSupportedTokenType | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
parameter | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 2 | ++ | ||
string | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
isNull | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
eq | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
neq | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
gt | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
gte | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
lt | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
lte | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
in | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
notIn | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
contains | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
notContains | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
andX | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
nandX | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
orX | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
norX | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
xorX | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ |
1 | <?php |
2 | |
3 | declare(strict_types=1); |
4 | |
5 | namespace Symftony\Xpression\Bridge\Doctrine\ORM; |
6 | |
7 | use Doctrine\ORM\Query\Expr; |
8 | use Symftony\Xpression\Exception\Expr\UnsupportedExpressionTypeException; |
9 | use Symftony\Xpression\Expr\ExpressionBuilderInterface; |
10 | use Symftony\Xpression\Lexer; |
11 | |
12 | class ExprAdapter implements ExpressionBuilderInterface |
13 | { |
14 | private Expr $expr; |
15 | |
16 | public function __construct(Expr $expr) |
17 | { |
18 | $this->expr = $expr; |
19 | } |
20 | |
21 | public function getSupportedTokenType(): int |
22 | { |
23 | return Lexer::T_ALL - Lexer::T_NOT_AND - Lexer::T_NOT_OR - Lexer::T_XOR; |
24 | } |
25 | |
26 | public function parameter(mixed $value, bool $isValue = false): mixed |
27 | { |
28 | return $isValue ? $this->expr->literal($value) : $value; |
29 | } |
30 | |
31 | public function string(mixed $value): mixed |
32 | { |
33 | return $this->expr->literal($value); |
34 | } |
35 | |
36 | public function isNull(string $field): mixed |
37 | { |
38 | return $this->expr->isNull($field); |
39 | } |
40 | |
41 | public function eq(string $field, mixed $value): mixed |
42 | { |
43 | return $this->expr->eq($field, $value); |
44 | } |
45 | |
46 | public function neq(string $field, mixed $value): mixed |
47 | { |
48 | return $this->expr->neq($field, $value); |
49 | } |
50 | |
51 | public function gt(string $field, mixed $value): mixed |
52 | { |
53 | return $this->expr->gt($field, $value); |
54 | } |
55 | |
56 | public function gte(string $field, mixed $value): mixed |
57 | { |
58 | return $this->expr->gte($field, $value); |
59 | } |
60 | |
61 | public function lt(string $field, mixed $value): mixed |
62 | { |
63 | return $this->expr->lt($field, $value); |
64 | } |
65 | |
66 | public function lte(string $field, mixed $value): mixed |
67 | { |
68 | return $this->expr->lte($field, $value); |
69 | } |
70 | |
71 | public function in(string $field, array $values): mixed |
72 | { |
73 | return $this->expr->in($field, $values); |
74 | } |
75 | |
76 | public function notIn(string $field, array $values): mixed |
77 | { |
78 | return $this->expr->notIn($field, $values); |
79 | } |
80 | |
81 | public function contains(string $field, mixed $value): mixed |
82 | { |
83 | return $this->expr->like($field, $value); |
84 | } |
85 | |
86 | public function notContains(string $field, mixed $value): mixed |
87 | { |
88 | return $this->expr->notLike($field, $value); |
89 | } |
90 | |
91 | public function andX(array $expressions): mixed |
92 | { |
93 | return $this->expr->andX(...$expressions); |
94 | } |
95 | |
96 | public function nandX(array $expressions): mixed |
97 | { |
98 | throw new UnsupportedExpressionTypeException('nandX'); |
99 | } |
100 | |
101 | public function orX(array $expressions): mixed |
102 | { |
103 | return $this->expr->orX(...$expressions); |
104 | } |
105 | |
106 | public function norX(array $expressions): mixed |
107 | { |
108 | throw new UnsupportedExpressionTypeException('norX'); |
109 | } |
110 | |
111 | public function xorX(array $expressions): mixed |
112 | { |
113 | throw new UnsupportedExpressionTypeException('xorX'); |
114 | } |
115 | } |
Class | +Coverage | +
---|
Class | +CRAP | +
---|
Method | +Coverage | +
---|
Method | +CRAP | +
---|
+ | Code Coverage |
+ ||||||||
+ | Lines |
+ Functions and Methods |
+ Classes and Traits |
+ ||||||
Total | +
+
+
+ |
+ 100.00% |
+ 20 / 20 |
+
+
+
+ |
+ 100.00% |
+ 20 / 20 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
ExprAdapter.php | +
+
+
+ |
+ 100.00% |
+ 20 / 20 |
+
+
+
+ |
+ 100.00% |
+ 20 / 20 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
Class | +Coverage | +
---|
Class | +CRAP | +
---|
+ | Code Coverage |
+ ||||||||
+ | Lines |
+ Functions and Methods |
+ Classes and Traits |
+ ||||||
Total | +
+
+
+ |
+ 97.62% |
+ 41 / 42 |
+
+
+
+ |
+ 97.50% |
+ 39 / 40 |
+
+
+
+ |
+ 50.00% |
+ 1 / 2 |
+
Common | +
+
+
+ |
+ 95.45% |
+ 21 / 22 |
+
+
+
+ |
+ 95.00% |
+ 19 / 20 |
+
+
+
+ |
+ 0.00% |
+ 0 / 1 |
+
ORM | +
+
+
+ |
+ 100.00% |
+ 20 / 20 |
+
+
+
+ |
+ 100.00% |
+ 20 / 20 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+ | Code Coverage |
+ |||||||||
+ | Lines |
+ Functions and Methods |
+ Classes and Traits |
+ |||||||
Total | +
+
+
+ |
+ 100.00% |
+ 19 / 19 |
+
+
+
+ |
+ 100.00% |
+ 19 / 19 |
+ CRAP | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
ExprBuilder | +
+
+
+ |
+ 100.00% |
+ 19 / 19 |
+
+
+
+ |
+ 100.00% |
+ 19 / 19 |
+ 19 | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
getSupportedTokenType | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
parameter | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
string | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
isNull | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
eq | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
neq | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
gt | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
gte | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
lt | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
lte | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
in | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
notIn | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
contains | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
notContains | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
andX | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
nandX | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
orX | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
norX | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
xorX | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ |
1 | <?php |
2 | |
3 | declare(strict_types=1); |
4 | |
5 | namespace Symftony\Xpression\Bridge\MongoDB; |
6 | |
7 | use Symftony\Xpression\Exception\Expr\UnsupportedExpressionTypeException; |
8 | use Symftony\Xpression\Expr\ExpressionBuilderInterface; |
9 | use Symftony\Xpression\Lexer; |
10 | |
11 | class ExprBuilder implements ExpressionBuilderInterface |
12 | { |
13 | public function getSupportedTokenType(): int |
14 | { |
15 | return Lexer::T_ALL - Lexer::T_XOR; |
16 | } |
17 | |
18 | public function parameter(mixed $value, bool $isValue = false): mixed |
19 | { |
20 | return $value; |
21 | } |
22 | |
23 | public function string(mixed $value): mixed |
24 | { |
25 | return $value; |
26 | } |
27 | |
28 | public function isNull(string $field): mixed |
29 | { |
30 | return [$field => null]; |
31 | } |
32 | |
33 | public function eq(string $field, mixed $value): mixed |
34 | { |
35 | return [$field => ['$eq' => $value]]; |
36 | } |
37 | |
38 | public function neq(string $field, mixed $value): mixed |
39 | { |
40 | return [$field => ['$ne' => $value]]; |
41 | } |
42 | |
43 | public function gt(string $field, mixed $value): mixed |
44 | { |
45 | return [$field => ['$gt' => $value]]; |
46 | } |
47 | |
48 | public function gte(string $field, mixed $value): mixed |
49 | { |
50 | return [$field => ['$gte' => $value]]; |
51 | } |
52 | |
53 | public function lt(string $field, mixed $value): mixed |
54 | { |
55 | return [$field => ['$lt' => $value]]; |
56 | } |
57 | |
58 | public function lte(string $field, mixed $value): mixed |
59 | { |
60 | return [$field => ['$lte' => $value]]; |
61 | } |
62 | |
63 | public function in(string $field, array $values): mixed |
64 | { |
65 | return [$field => ['$in' => $values]]; |
66 | } |
67 | |
68 | public function notIn(string $field, array $values): mixed |
69 | { |
70 | return [$field => ['$nin' => $values]]; |
71 | } |
72 | |
73 | public function contains(string $field, mixed $value): mixed |
74 | { |
75 | return [$field => ['$regex' => $value]]; |
76 | } |
77 | |
78 | public function notContains(string $field, mixed $value): mixed |
79 | { |
80 | return ['$not' => $this->contains($field, $value)]; |
81 | } |
82 | |
83 | public function andX(array $expressions): mixed |
84 | { |
85 | return ['$and' => $expressions]; |
86 | } |
87 | |
88 | // Not A AND B = Not A OR Not B |
89 | public function nandX(array $expressions): mixed |
90 | { |
91 | return $this->orX(array_map(static fn ($expression) => ['$not' => $expression], $expressions)); |
92 | } |
93 | |
94 | public function orX(array $expressions): mixed |
95 | { |
96 | return ['$or' => $expressions]; |
97 | } |
98 | |
99 | public function norX(array $expressions): mixed |
100 | { |
101 | return ['$nor' => $expressions]; |
102 | } |
103 | |
104 | public function xorX(array $expressions): mixed |
105 | { |
106 | throw new UnsupportedExpressionTypeException('xorX'); |
107 | } |
108 | } |
Class | +Coverage | +
---|
Class | +CRAP | +
---|
Method | +Coverage | +
---|
Method | +CRAP | +
---|
+ | Code Coverage |
+ ||||||||
+ | Lines |
+ Functions and Methods |
+ Classes and Traits |
+ ||||||
Total | +
+
+
+ |
+ 100.00% |
+ 19 / 19 |
+
+
+
+ |
+ 100.00% |
+ 19 / 19 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
ExprBuilder.php | +
+
+
+ |
+ 100.00% |
+ 19 / 19 |
+
+
+
+ |
+ 100.00% |
+ 19 / 19 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
Class | +Coverage | +
---|
Class | +CRAP | +
---|
+ | Code Coverage |
+ ||||||||
+ | Lines |
+ Functions and Methods |
+ Classes and Traits |
+ ||||||
Total | +
+
+
+ |
+ 98.36% |
+ 60 / 61 |
+
+
+
+ |
+ 98.31% |
+ 58 / 59 |
+
+
+
+ |
+ 66.67% |
+ 2 / 3 |
+
Doctrine | +
+
+
+ |
+ 97.62% |
+ 41 / 42 |
+
+
+
+ |
+ 97.50% |
+ 39 / 40 |
+
+
+
+ |
+ 50.00% |
+ 1 / 2 |
+
MongoDB | +
+
+
+ |
+ 100.00% |
+ 19 / 19 |
+
+
+
+ |
+ 100.00% |
+ 19 / 19 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+ | Code Coverage |
+ |||||||||
+ | Lines |
+ Functions and Methods |
+ Classes and Traits |
+ |||||||
Total | +
+
+
+ |
+ 96.67% |
+ 58 / 60 |
+
+
+
+ |
+ 95.00% |
+ 19 / 20 |
+ CRAP | +
+
+
+ |
+ 0.00% |
+ 0 / 1 |
+
ClosureExpressionBuilder | +
+
+
+ |
+ 96.67% |
+ 58 / 60 |
+
+
+
+ |
+ 95.00% |
+ 19 / 20 |
+ 34 | +
+
+
+ |
+ 0.00% |
+ 0 / 1 |
+
getObjectFieldValue | +
+
+
+ |
+ 90.91% |
+ 20 / 22 |
+
+
+
+ |
+ 0.00% |
+ 0 / 1 |
+ 9.06 | ++ | ||
getSupportedTokenType | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
parameter | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
string | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
isNull | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
eq | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
neq | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
gt | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
gte | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
lt | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
lte | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
in | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
notIn | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
contains | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
notContains | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
andX | +
+
+
+ |
+ 100.00% |
+ 6 / 6 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 3 | ++ | ||
nandX | +
+
+
+ |
+ 100.00% |
+ 2 / 2 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
orX | +
+
+
+ |
+ 100.00% |
+ 6 / 6 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 3 | ++ | ||
norX | +
+
+
+ |
+ 100.00% |
+ 2 / 2 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
xorX | +
+
+
+ |
+ 100.00% |
+ 8 / 8 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 3 | ++ |
1 | <?php |
2 | |
3 | declare(strict_types=1); |
4 | |
5 | namespace Symftony\Xpression\Expr; |
6 | |
7 | use Symftony\Xpression\Lexer; |
8 | |
9 | class ClosureExpressionBuilder implements ExpressionBuilderInterface |
10 | { |
11 | public static function getObjectFieldValue(mixed $object, mixed $field): mixed |
12 | { |
13 | if (\is_array($object)) { |
14 | return $object[$field]; |
15 | } |
16 | |
17 | $accessors = ['get', 'is']; |
18 | |
19 | foreach ($accessors as $accessor) { |
20 | $accessor .= $field; |
21 | |
22 | if (!method_exists($object, $accessor)) { |
23 | continue; |
24 | } |
25 | |
26 | return $object->{$accessor}(); |
27 | } |
28 | |
29 | // __call should be triggered for get. |
30 | $accessor = $accessors[0].$field; |
31 | |
32 | if (method_exists($object, '__call')) { |
33 | return $object->{$accessor}(); |
34 | } |
35 | |
36 | if ($object instanceof \ArrayAccess) { |
37 | return $object[$field]; |
38 | } |
39 | |
40 | if (isset($object->{$field})) { |
41 | return $object->{$field}; |
42 | } |
43 | |
44 | // camelcase field name to support different variable naming conventions |
45 | $ccField = preg_replace_callback('/_(.?)/', static fn ($matches) => strtoupper($matches[1]), $field); |
46 | |
47 | foreach ($accessors as $accessor) { |
48 | $accessor .= $ccField; |
49 | |
50 | if (!method_exists($object, $accessor)) { |
51 | continue; |
52 | } |
53 | |
54 | return $object->{$accessor}(); |
55 | } |
56 | |
57 | return $object->{$field}; |
58 | } |
59 | |
60 | public function getSupportedTokenType(): int |
61 | { |
62 | return Lexer::T_ALL; |
63 | } |
64 | |
65 | /** |
66 | * @param bool $isValue |
67 | * @param mixed $value |
68 | */ |
69 | public function parameter($value, $isValue = false): mixed |
70 | { |
71 | return $value; |
72 | } |
73 | |
74 | public function string(mixed $value): mixed |
75 | { |
76 | return $value; |
77 | } |
78 | |
79 | public function isNull(string $field): mixed |
80 | { |
81 | return static fn ($object) => null === ClosureExpressionBuilder::getObjectFieldValue($object, $field); |
82 | } |
83 | |
84 | public function eq(string $field, mixed $value): mixed |
85 | { |
86 | return static fn ($object) => ClosureExpressionBuilder::getObjectFieldValue($object, $field) === $value; |
87 | } |
88 | |
89 | public function neq(string $field, mixed $value): mixed |
90 | { |
91 | return static fn ($object) => ClosureExpressionBuilder::getObjectFieldValue($object, $field) !== $value; |
92 | } |
93 | |
94 | public function gt(string $field, mixed $value): mixed |
95 | { |
96 | return static fn ($object) => ClosureExpressionBuilder::getObjectFieldValue($object, $field) > $value; |
97 | } |
98 | |
99 | public function gte(string $field, mixed $value): mixed |
100 | { |
101 | return static fn ($object) => ClosureExpressionBuilder::getObjectFieldValue($object, $field) >= $value; |
102 | } |
103 | |
104 | public function lt(string $field, mixed $value): mixed |
105 | { |
106 | return static fn ($object) => ClosureExpressionBuilder::getObjectFieldValue($object, $field) < $value; |
107 | } |
108 | |
109 | public function lte(string $field, mixed $value): mixed |
110 | { |
111 | return static fn ($object) => ClosureExpressionBuilder::getObjectFieldValue($object, $field) <= $value; |
112 | } |
113 | |
114 | public function in(string $field, array $values): mixed |
115 | { |
116 | return static fn ($object) => \in_array(ClosureExpressionBuilder::getObjectFieldValue($object, $field), $values, true); |
117 | } |
118 | |
119 | public function notIn(string $field, array $values): mixed |
120 | { |
121 | return static fn ($object) => !\in_array(ClosureExpressionBuilder::getObjectFieldValue($object, $field), $values, true); |
122 | } |
123 | |
124 | public function contains(string $field, mixed $value): mixed |
125 | { |
126 | return static fn ($object) => str_contains(ClosureExpressionBuilder::getObjectFieldValue($object, $field), $value); |
127 | } |
128 | |
129 | public function notContains(string $field, mixed $value): mixed |
130 | { |
131 | return static fn ($object) => !str_contains(ClosureExpressionBuilder::getObjectFieldValue($object, $field), $value); |
132 | } |
133 | |
134 | public function andX(array $expressions): mixed |
135 | { |
136 | return static function ($object) use ($expressions) { |
137 | foreach ($expressions as $expression) { |
138 | if (!$expression($object)) { |
139 | return false; |
140 | } |
141 | } |
142 | |
143 | return true; |
144 | }; |
145 | } |
146 | |
147 | public function nandX(array $expressions): mixed |
148 | { |
149 | $self = $this; |
150 | |
151 | return static fn ($object) => !$self->andX($expressions)($object); |
152 | } |
153 | |
154 | public function orX(array $expressions): mixed |
155 | { |
156 | return static function ($object) use ($expressions) { |
157 | foreach ($expressions as $expression) { |
158 | if ($expression($object)) { |
159 | return true; |
160 | } |
161 | } |
162 | |
163 | return false; |
164 | }; |
165 | } |
166 | |
167 | public function norX(array $expressions): mixed |
168 | { |
169 | $self = $this; |
170 | |
171 | return static fn ($object) => !$self->orX($expressions)($object); |
172 | } |
173 | |
174 | public function xorX(array $expressions): mixed |
175 | { |
176 | return static function ($object) use ($expressions) { |
177 | $result = 0; |
178 | foreach ($expressions as $expression) { |
179 | if ($expression($object)) { |
180 | ++$result; |
181 | } |
182 | } |
183 | |
184 | $countExpressions = \count($expressions); |
185 | |
186 | return 1 === $result | (2 < $countExpressions & $result === $countExpressions); |
187 | }; |
188 | } |
189 | } |
+ | Code Coverage |
+ |||||||||
+ | Lines |
+ Functions and Methods |
+ Classes and Traits |
+ |||||||
Total | ++ | n/a |
+ 0 / 0 |
+ + | n/a |
+ 0 / 0 |
+ CRAP | ++ | n/a |
+ 0 / 0 |
+
1 | <?php |
2 | |
3 | declare(strict_types=1); |
4 | |
5 | namespace Symftony\Xpression\Expr; |
6 | |
7 | interface ExpressionBuilderInterface |
8 | { |
9 | /** |
10 | * Must return all supported token type. |
11 | */ |
12 | public function getSupportedTokenType(): int; |
13 | |
14 | public function parameter(mixed $value, bool $isValue = false): mixed; |
15 | |
16 | public function string(mixed $value): mixed; |
17 | |
18 | public function isNull(string $field): mixed; |
19 | |
20 | public function eq(string $field, mixed $value): mixed; |
21 | |
22 | public function neq(string $field, mixed $value): mixed; |
23 | |
24 | public function gt(string $field, mixed $value): mixed; |
25 | |
26 | public function gte(string $field, mixed $value): mixed; |
27 | |
28 | public function lt(string $field, mixed $value): mixed; |
29 | |
30 | public function lte(string $field, mixed $value): mixed; |
31 | |
32 | public function in(string $field, array $values): mixed; |
33 | |
34 | public function notIn(string $field, array $values): mixed; |
35 | |
36 | public function contains(string $field, mixed $value): mixed; |
37 | |
38 | public function notContains(string $field, mixed $value): mixed; |
39 | |
40 | public function andX(array $expressions): mixed; |
41 | |
42 | public function nandX(array $expressions): mixed; |
43 | |
44 | public function orX(array $expressions): mixed; |
45 | |
46 | public function norX(array $expressions): mixed; |
47 | |
48 | public function xorX(array $expressions): mixed; |
49 | } |
+ | Code Coverage |
+ |||||||||
+ | Lines |
+ Functions and Methods |
+ Classes and Traits |
+ |||||||
Total | +
+
+
+ |
+ 100.00% |
+ 25 / 25 |
+
+
+
+ |
+ 100.00% |
+ 20 / 20 |
+ CRAP | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
HtmlExpressionBuilder | +
+
+
+ |
+ 100.00% |
+ 25 / 25 |
+
+
+
+ |
+ 100.00% |
+ 20 / 20 |
+ 22 | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
__construct | +
+
+
+ |
+ 100.00% |
+ 6 / 6 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 3 | ++ | ||
getSupportedTokenType | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
parameter | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
string | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
isNull | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
eq | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
neq | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
gt | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
gte | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
lt | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
lte | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
in | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
notIn | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
contains | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
notContains | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
andX | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
nandX | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
orX | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
norX | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
xorX | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ |
1 | <?php |
2 | |
3 | declare(strict_types=1); |
4 | |
5 | namespace Symftony\Xpression\Expr; |
6 | |
7 | use Symftony\Xpression\Lexer; |
8 | |
9 | class HtmlExpressionBuilder implements ExpressionBuilderInterface |
10 | { |
11 | /** |
12 | * This callable is use to delegate the html generation to a third party |
13 | * eg: $comparisonHtmlBuilder($field, $operator, $value) |
14 | * it must return the html code. |
15 | * |
16 | * @var callable |
17 | */ |
18 | private $comparisonHtmlBuilder; |
19 | |
20 | /** |
21 | * This callable is use to delegate the html generation to a third party |
22 | * eg: $compositeHtmlBuilder(array $expressions, $type) |
23 | * it must return the html code. |
24 | * |
25 | * @var callable |
26 | */ |
27 | private $compositeHtmlBuilder; |
28 | |
29 | public function __construct(callable $comparisonHtmlBuilder = null, callable $compositeHtmlBuilder = null) |
30 | { |
31 | $this->comparisonHtmlBuilder = $comparisonHtmlBuilder ?: static fn ($field, $operator, $value) => sprintf('<div>%s %s %s</div>', $field, $operator, $value); |
32 | $this->compositeHtmlBuilder = $compositeHtmlBuilder ?: static fn (array $expressions, $type) => str_replace( |
33 | ['{type}', '{expressions}'], |
34 | [$type, implode('', $expressions)], |
35 | '<fieldset><legend>{type}</legend>{expressions}</fieldset>' |
36 | ); |
37 | } |
38 | |
39 | public function getSupportedTokenType(): int |
40 | { |
41 | return Lexer::T_ALL; |
42 | } |
43 | |
44 | public function parameter(mixed $value, bool $isValue = false): mixed |
45 | { |
46 | return $value; |
47 | } |
48 | |
49 | public function string(mixed $value): mixed |
50 | { |
51 | return '"'.$value.'"'; |
52 | } |
53 | |
54 | public function isNull(string $field): mixed |
55 | { |
56 | return ($this->comparisonHtmlBuilder)($field, 'is', 'null'); |
57 | } |
58 | |
59 | public function eq(string $field, mixed $value): mixed |
60 | { |
61 | return ($this->comparisonHtmlBuilder)($field, '=', $value); |
62 | } |
63 | |
64 | public function neq(string $field, mixed $value): mixed |
65 | { |
66 | return ($this->comparisonHtmlBuilder)($field, '≠', $value); |
67 | } |
68 | |
69 | public function gt(string $field, mixed $value): mixed |
70 | { |
71 | return ($this->comparisonHtmlBuilder)($field, '>', $value); |
72 | } |
73 | |
74 | public function gte(string $field, mixed $value): mixed |
75 | { |
76 | return ($this->comparisonHtmlBuilder)($field, '≥', $value); |
77 | } |
78 | |
79 | public function lt(string $field, mixed $value): mixed |
80 | { |
81 | return ($this->comparisonHtmlBuilder)($field, '<', $value); |
82 | } |
83 | |
84 | public function lte(string $field, mixed $value): mixed |
85 | { |
86 | return ($this->comparisonHtmlBuilder)($field, '≤', $value); |
87 | } |
88 | |
89 | public function in(string $field, array $values): mixed |
90 | { |
91 | return ($this->comparisonHtmlBuilder)($field, 'value in', implode(', ', $values)); |
92 | } |
93 | |
94 | public function notIn(string $field, array $values): mixed |
95 | { |
96 | return ($this->comparisonHtmlBuilder)($field, 'value not in', implode(', ', $values)); |
97 | } |
98 | |
99 | public function contains(string $field, mixed $value): mixed |
100 | { |
101 | return ($this->comparisonHtmlBuilder)($field, 'contains', $value); |
102 | } |
103 | |
104 | public function notContains(string $field, mixed $value): mixed |
105 | { |
106 | return ($this->comparisonHtmlBuilder)($field, 'notContains', $value); |
107 | } |
108 | |
109 | public function andX(array $expressions): mixed |
110 | { |
111 | return ($this->compositeHtmlBuilder)($expressions, 'and'); |
112 | } |
113 | |
114 | public function nandX(array $expressions): mixed |
115 | { |
116 | return ($this->compositeHtmlBuilder)($expressions, 'not-and'); |
117 | } |
118 | |
119 | public function orX(array $expressions): mixed |
120 | { |
121 | return ($this->compositeHtmlBuilder)($expressions, 'or'); |
122 | } |
123 | |
124 | public function norX(array $expressions): mixed |
125 | { |
126 | return ($this->compositeHtmlBuilder)($expressions, 'not-or'); |
127 | } |
128 | |
129 | public function xorX(array $expressions): mixed |
130 | { |
131 | return ($this->compositeHtmlBuilder)($expressions, 'exclusive-or'); |
132 | } |
133 | } |
+ | Code Coverage |
+ |||||||||
+ | Lines |
+ Functions and Methods |
+ Classes and Traits |
+ |||||||
Total | +
+
+
+ |
+ 96.43% |
+ 27 / 28 |
+
+
+
+ |
+ 95.24% |
+ 20 / 21 |
+ CRAP | +
+
+
+ |
+ 0.00% |
+ 0 / 1 |
+
MapperExpressionBuilder | +
+
+
+ |
+ 96.43% |
+ 27 / 28 |
+
+
+
+ |
+ 95.24% |
+ 20 / 21 |
+ 26 | +
+
+
+ |
+ 0.00% |
+ 0 / 1 |
+
__construct | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
getSupportedTokenType | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
parameter | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
string | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
isNull | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
eq | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
neq | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
gt | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
gte | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
lt | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
lte | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
in | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
notIn | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
contains | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
notContains | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
andX | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
nandX | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
orX | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
norX | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
xorX | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
mapField | +
+
+
+ |
+ 87.50% |
+ 7 / 8 |
+
+
+
+ |
+ 0.00% |
+ 0 / 1 |
+ 6.07 | ++ |
1 | <?php |
2 | |
3 | declare(strict_types=1); |
4 | |
5 | namespace Symftony\Xpression\Expr; |
6 | |
7 | class MapperExpressionBuilder implements ExpressionBuilderInterface |
8 | { |
9 | /** |
10 | * @param string[] $fieldMapping |
11 | */ |
12 | public function __construct( |
13 | private ExpressionBuilderInterface $expressionBuilder, |
14 | private array $fieldMapping = [], |
15 | ) {} |
16 | |
17 | public function getSupportedTokenType(): int |
18 | { |
19 | return $this->expressionBuilder->getSupportedTokenType(); |
20 | } |
21 | |
22 | public function parameter(mixed $value, bool $isValue = false): mixed |
23 | { |
24 | return $this->expressionBuilder->parameter($value, $isValue); |
25 | } |
26 | |
27 | public function string(mixed $value): mixed |
28 | { |
29 | return $this->expressionBuilder->string($value); |
30 | } |
31 | |
32 | public function isNull(string $field): mixed |
33 | { |
34 | return $this->expressionBuilder->isNull($this->mapField($field)); |
35 | } |
36 | |
37 | public function eq(string $field, mixed $value): mixed |
38 | { |
39 | return $this->expressionBuilder->eq($this->mapField($field), $value); |
40 | } |
41 | |
42 | public function neq(string $field, mixed $value): mixed |
43 | { |
44 | return $this->expressionBuilder->neq($this->mapField($field), $value); |
45 | } |
46 | |
47 | public function gt(string $field, mixed $value): mixed |
48 | { |
49 | return $this->expressionBuilder->gt($this->mapField($field), $value); |
50 | } |
51 | |
52 | public function gte(string $field, mixed $value): mixed |
53 | { |
54 | return $this->expressionBuilder->gte($this->mapField($field), $value); |
55 | } |
56 | |
57 | public function lt(string $field, mixed $value): mixed |
58 | { |
59 | return $this->expressionBuilder->lt($this->mapField($field), $value); |
60 | } |
61 | |
62 | public function lte(string $field, mixed $value): mixed |
63 | { |
64 | return $this->expressionBuilder->lte($this->mapField($field), $value); |
65 | } |
66 | |
67 | public function in(string $field, array $values): mixed |
68 | { |
69 | return $this->expressionBuilder->in($this->mapField($field), $values); |
70 | } |
71 | |
72 | public function notIn(string $field, array $values): mixed |
73 | { |
74 | return $this->expressionBuilder->notIn($this->mapField($field), $values); |
75 | } |
76 | |
77 | public function contains(string $field, mixed $value): mixed |
78 | { |
79 | return $this->expressionBuilder->contains($this->mapField($field), $value); |
80 | } |
81 | |
82 | public function notContains(string $field, mixed $value): mixed |
83 | { |
84 | return $this->expressionBuilder->notContains($this->mapField($field), $value); |
85 | } |
86 | |
87 | public function andX(array $expressions): mixed |
88 | { |
89 | return $this->expressionBuilder->andX($expressions); |
90 | } |
91 | |
92 | public function nandX(array $expressions): mixed |
93 | { |
94 | return $this->expressionBuilder->nandX($expressions); |
95 | } |
96 | |
97 | public function orX(array $expressions): mixed |
98 | { |
99 | return $this->expressionBuilder->orX($expressions); |
100 | } |
101 | |
102 | public function norX(array $expressions): mixed |
103 | { |
104 | return $this->expressionBuilder->norX($expressions); |
105 | } |
106 | |
107 | public function xorX(array $expressions): mixed |
108 | { |
109 | return $this->expressionBuilder->xorX($expressions); |
110 | } |
111 | |
112 | private function mapField(mixed $field): mixed |
113 | { |
114 | if ( |
115 | \is_array($field) |
116 | || \is_object($field) && !method_exists($field, '__toString') |
117 | ) { |
118 | return $field; |
119 | } |
120 | |
121 | if (\array_key_exists((string) $field, $this->fieldMapping)) { |
122 | return sprintf($this->fieldMapping[(string) $field], $field); |
123 | } |
124 | |
125 | if (\array_key_exists('*', $this->fieldMapping)) { |
126 | return sprintf($this->fieldMapping['*'], $field); |
127 | } |
128 | |
129 | return $field; |
130 | } |
131 | } |
Class | +Coverage | +
---|
Class | +CRAP | +
---|
+ | Code Coverage |
+ ||||||||
+ | Lines |
+ Functions and Methods |
+ Classes and Traits |
+ ||||||
Total | +
+
+
+ |
+ 97.35% |
+ 110 / 113 |
+
+
+
+ |
+ 96.72% |
+ 59 / 61 |
+
+
+
+ |
+ 33.33% |
+ 1 / 3 |
+
ClosureExpressionBuilder.php | +
+
+
+ |
+ 96.67% |
+ 58 / 60 |
+
+
+
+ |
+ 95.00% |
+ 19 / 20 |
+
+
+
+ |
+ 0.00% |
+ 0 / 1 |
+
ExpressionBuilderInterface.php | ++ | n/a |
+ 0 / 0 |
+ + | n/a |
+ 0 / 0 |
+ + | n/a |
+ 0 / 0 |
+
HtmlExpressionBuilder.php | +
+
+
+ |
+ 100.00% |
+ 25 / 25 |
+
+
+
+ |
+ 100.00% |
+ 20 / 20 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
MapperExpressionBuilder.php | +
+
+
+ |
+ 96.43% |
+ 27 / 28 |
+
+
+
+ |
+ 95.24% |
+ 20 / 21 |
+
+
+
+ |
+ 0.00% |
+ 0 / 1 |
+
+ | Code Coverage |
+ |||||||||
+ | Lines |
+ Functions and Methods |
+ Classes and Traits |
+ |||||||
Total | +
+
+
+ |
+ 100.00% |
+ 152 / 152 |
+
+
+
+ |
+ 100.00% |
+ 4 / 4 |
+ CRAP | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
Lexer | +
+
+
+ |
+ 100.00% |
+ 152 / 152 |
+
+
+
+ |
+ 100.00% |
+ 4 / 4 |
+ 59 | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
getTokenSyntax | +
+
+
+ |
+ 100.00% |
+ 50 / 50 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 25 | ++ | ||
getCatchablePatterns | +
+
+
+ |
+ 100.00% |
+ 9 / 9 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
getNonCatchablePatterns | +
+
+
+ |
+ 100.00% |
+ 4 / 4 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
getType | +
+
+
+ |
+ 100.00% |
+ 89 / 89 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 32 | ++ |
1 | <?php |
2 | |
3 | declare(strict_types=1); |
4 | |
5 | namespace Symftony\Xpression; |
6 | |
7 | use Doctrine\Common\Lexer\AbstractLexer; |
8 | use Symftony\Xpression\Exception\Lexer\UnknownTokenTypeException; |
9 | |
10 | class Lexer extends AbstractLexer |
11 | { |
12 | public const T_NONE = 0; |
13 | public const T_ALL = 2 ** 24 - 1; |
14 | |
15 | // Punctuation |
16 | public const T_COMMA = 2 ** 0; |
17 | |
18 | // Operand |
19 | public const T_OPERAND = 2 ** 1 + 2 ** 2 + 2 ** 3 + 2 ** 4; |
20 | public const T_INTEGER = 2 ** 1; |
21 | public const T_STRING = 2 ** 2; |
22 | public const T_INPUT_PARAMETER = 2 ** 3; |
23 | public const T_FLOAT = 2 ** 4; |
24 | |
25 | // Comparison operator |
26 | public const T_COMPARISON = 2 ** 5 + 2 ** 6 + 2 ** 7 + 2 ** 8 + 2 ** 9 + 2 ** 10 + 2 ** 18 + 2 ** 19 + 2 ** 21 + 2 ** 22; |
27 | public const T_EQUALS = 2 ** 5; |
28 | public const T_NOT_EQUALS = 2 ** 6; |
29 | public const T_GREATER_THAN = 2 ** 7; |
30 | public const T_GREATER_THAN_EQUALS = 2 ** 8; |
31 | public const T_LOWER_THAN = 2 ** 9; |
32 | public const T_LOWER_THAN_EQUALS = 2 ** 10; |
33 | |
34 | // Composite operator |
35 | public const T_COMPOSITE = 2 ** 11 + 2 ** 12 + 2 ** 13 + 2 ** 14 + 2 ** 15; |
36 | public const T_AND = 2 ** 11; |
37 | public const T_NOT_AND = 2 ** 12; |
38 | public const T_OR = 2 ** 13; |
39 | public const T_NOT_OR = 2 ** 14; |
40 | public const T_XOR = 2 ** 15; |
41 | |
42 | // Brace |
43 | public const T_OPEN_PARENTHESIS = 2 ** 16; |
44 | public const T_CLOSE_PARENTHESIS = 2 ** 17; |
45 | public const T_OPEN_SQUARE_BRACKET = 2 ** 18; |
46 | public const T_NOT_OPEN_SQUARE_BRACKET = 2 ** 19; |
47 | public const T_CLOSE_SQUARE_BRACKET = 2 ** 20; |
48 | public const T_DOUBLE_OPEN_CURLY_BRACKET = 2 ** 21; |
49 | public const T_NOT_DOUBLE_OPEN_CURLY_BRACKET = 2 ** 22; |
50 | public const T_DOUBLE_CLOSE_CURLY_BRACKET = 2 ** 23; |
51 | |
52 | /** |
53 | * @return string[] |
54 | */ |
55 | public static function getTokenSyntax(mixed $tokenType): array |
56 | { |
57 | $tokenSyntax = []; |
58 | // Punctuation |
59 | if ($tokenType & self::T_COMMA) { |
60 | $tokenSyntax[] = ','; |
61 | } |
62 | |
63 | // Recognize numeric values |
64 | if ($tokenType & self::T_FLOAT) { |
65 | $tokenSyntax[] = 'simple float'; |
66 | } |
67 | if ($tokenType & self::T_INTEGER) { |
68 | $tokenSyntax[] = 'simple integer'; |
69 | } |
70 | if ($tokenType & self::T_INPUT_PARAMETER) { |
71 | $tokenSyntax[] = '/[a-z_][a-z0-9_]*/'; |
72 | } |
73 | |
74 | // Recognize quoted strings |
75 | if ($tokenType & self::T_STRING) { |
76 | $tokenSyntax[] = '"value" or \'value\''; |
77 | } |
78 | |
79 | // Comparison operator |
80 | if ($tokenType & self::T_EQUALS) { |
81 | $tokenSyntax[] = '='; |
82 | } |
83 | if ($tokenType & self::T_NOT_EQUALS) { |
84 | $tokenSyntax[] = '≠or !='; |
85 | } |
86 | if ($tokenType & self::T_GREATER_THAN) { |
87 | $tokenSyntax[] = '>'; |
88 | } |
89 | if ($tokenType & self::T_GREATER_THAN_EQUALS) { |
90 | $tokenSyntax[] = '≥ or >='; |
91 | } |
92 | if ($tokenType & self::T_LOWER_THAN) { |
93 | $tokenSyntax[] = '<'; |
94 | } |
95 | if ($tokenType & self::T_LOWER_THAN_EQUALS) { |
96 | $tokenSyntax[] = '≤ or <='; |
97 | } |
98 | |
99 | // Composite operator |
100 | if ($tokenType & self::T_AND) { |
101 | $tokenSyntax[] = '&'; |
102 | } |
103 | if ($tokenType & self::T_NOT_AND) { |
104 | $tokenSyntax[] = '!&'; |
105 | } |
106 | if ($tokenType & self::T_OR) { |
107 | $tokenSyntax[] = '|'; |
108 | } |
109 | if ($tokenType & self::T_NOT_OR) { |
110 | $tokenSyntax[] = '!|'; |
111 | } |
112 | if ($tokenType & self::T_XOR) { |
113 | $tokenSyntax[] = '⊕ or ^|'; |
114 | } |
115 | |
116 | // Brace |
117 | if ($tokenType & self::T_OPEN_PARENTHESIS) { |
118 | $tokenSyntax[] = '('; |
119 | } |
120 | if ($tokenType & self::T_CLOSE_PARENTHESIS) { |
121 | $tokenSyntax[] = ')'; |
122 | } |
123 | if ($tokenType & self::T_OPEN_SQUARE_BRACKET) { |
124 | $tokenSyntax[] = '['; |
125 | } |
126 | if ($tokenType & self::T_NOT_OPEN_SQUARE_BRACKET) { |
127 | $tokenSyntax[] = '!['; |
128 | } |
129 | if ($tokenType & self::T_CLOSE_SQUARE_BRACKET) { |
130 | $tokenSyntax[] = ']'; |
131 | } |
132 | if ($tokenType & self::T_DOUBLE_OPEN_CURLY_BRACKET) { |
133 | $tokenSyntax[] = '{{'; |
134 | } |
135 | if ($tokenType & self::T_NOT_DOUBLE_OPEN_CURLY_BRACKET) { |
136 | $tokenSyntax[] = '!{{'; |
137 | } |
138 | if ($tokenType & self::T_DOUBLE_CLOSE_CURLY_BRACKET) { |
139 | $tokenSyntax[] = '}}'; |
140 | } |
141 | |
142 | return $tokenSyntax; |
143 | } |
144 | |
145 | /** |
146 | * @return array |
147 | */ |
148 | protected function getCatchablePatterns() |
149 | { |
150 | return [ |
151 | "'(?:[^']|'')*'", // quoted strings |
152 | '"(?:[^"]|"")*"', // quoted strings |
153 | '\^\||⊕|!&|&|!\||\|', // Composite operator |
154 | '≤|≥|≠|<=|>=|!=|<|>|=|\[|!\[|\]|!{{|{{|}}', // Comparison operator |
155 | '[a-z_][a-z0-9_\.\-]*', // identifier or qualified name |
156 | '(?:[+-]?[0-9]*(?:[\.][0-9]+)*)', // numbers |
157 | // '(?:[+-]?(?:(?:(?:[0-9]+|(?:[0-9]*[\.][0-9]+)|(?:[0-9]+[\.][0-9]*))[eE][+-]?[0-9]+)|(?:[0-9]*[\.][0-9]+)|(?:[0-9]+[\.][0-9]*)))', // number extended all float (.5 / 1.5 / -1.2e3) |
158 | ]; |
159 | } |
160 | |
161 | /** |
162 | * @return array |
163 | */ |
164 | protected function getNonCatchablePatterns() |
165 | { |
166 | return [ |
167 | '\s+', |
168 | '(.)', |
169 | ]; |
170 | } |
171 | |
172 | /** |
173 | * @param string $value |
174 | * |
175 | * @return int |
176 | * |
177 | * @throws UnknownTokenTypeException |
178 | */ |
179 | protected function getType(&$value) |
180 | { |
181 | switch (true) { |
182 | // Punctuation |
183 | case ',' === $value[0]: |
184 | $type = self::T_COMMA; |
185 | |
186 | break; |
187 | |
188 | // Recognize numeric values |
189 | case is_numeric($value): |
190 | if (str_contains($value, '.') || false !== stripos($value, 'e')) { |
191 | $value = (float)$value; |
192 | $type = self::T_FLOAT; |
193 | |
194 | break; |
195 | } |
196 | |
197 | $value = (int)$value; |
198 | $type = self::T_INTEGER; |
199 | |
200 | break; |
201 | |
202 | // Recognize quoted strings |
203 | case '"' === $value[0]: |
204 | $value = str_replace('""', '"', substr($value, 1, \strlen($value) - 2)); |
205 | |
206 | $type = self::T_STRING; |
207 | |
208 | break; |
209 | |
210 | case "'" === $value[0]: |
211 | $value = str_replace("''", "'", substr($value, 1, \strlen($value) - 2)); |
212 | |
213 | $type = self::T_STRING; |
214 | |
215 | break; |
216 | |
217 | case preg_match('/[a-z_][a-z0-9_]*/i', $value): |
218 | $type = self::T_INPUT_PARAMETER; |
219 | |
220 | break; |
221 | |
222 | // Comparison operator |
223 | case '=' === $value: |
224 | $type = self::T_EQUALS; |
225 | |
226 | break; |
227 | |
228 | case '≠' === $value: |
229 | case '!=' === $value: |
230 | $value = '≠'; |
231 | $type = self::T_NOT_EQUALS; |
232 | |
233 | break; |
234 | |
235 | case '>' === $value: |
236 | $type = self::T_GREATER_THAN; |
237 | |
238 | break; |
239 | |
240 | case '>=' === $value: |
241 | case '≥' === $value: |
242 | $value = '≥'; |
243 | $type = self::T_GREATER_THAN_EQUALS; |
244 | |
245 | break; |
246 | |
247 | case '<' === $value: |
248 | $type = self::T_LOWER_THAN; |
249 | |
250 | break; |
251 | |
252 | case '<=' === $value: |
253 | case '≤' === $value: |
254 | $value = '≤'; |
255 | $type = self::T_LOWER_THAN_EQUALS; |
256 | |
257 | break; |
258 | |
259 | // Composite operator |
260 | case '&' === $value: |
261 | $type = self::T_AND; |
262 | |
263 | break; |
264 | |
265 | case '!&' === $value: |
266 | $type = self::T_NOT_AND; |
267 | |
268 | break; |
269 | |
270 | case '|' === $value: |
271 | $type = self::T_OR; |
272 | |
273 | break; |
274 | |
275 | case '!|' === $value: |
276 | $type = self::T_NOT_OR; |
277 | |
278 | break; |
279 | |
280 | case '^|' === $value: |
281 | case '⊕' === $value: |
282 | $value = '⊕'; |
283 | $type = self::T_XOR; |
284 | |
285 | break; |
286 | |
287 | // Brace |
288 | case '(' === $value: |
289 | $type = self::T_OPEN_PARENTHESIS; |
290 | |
291 | break; |
292 | |
293 | case ')' === $value: |
294 | $type = self::T_CLOSE_PARENTHESIS; |
295 | |
296 | break; |
297 | |
298 | case '[' === $value: |
299 | $type = self::T_OPEN_SQUARE_BRACKET; |
300 | |
301 | break; |
302 | |
303 | case '![' === $value: |
304 | $type = self::T_NOT_OPEN_SQUARE_BRACKET; |
305 | |
306 | break; |
307 | |
308 | case ']' === $value: |
309 | $type = self::T_CLOSE_SQUARE_BRACKET; |
310 | |
311 | break; |
312 | |
313 | case '{{' === $value: |
314 | $type = self::T_DOUBLE_OPEN_CURLY_BRACKET; |
315 | |
316 | break; |
317 | |
318 | case '!{{' === $value: |
319 | $type = self::T_NOT_DOUBLE_OPEN_CURLY_BRACKET; |
320 | |
321 | break; |
322 | |
323 | case '}}' === $value: |
324 | $type = self::T_DOUBLE_CLOSE_CURLY_BRACKET; |
325 | |
326 | break; |
327 | |
328 | // Default |
329 | default: |
330 | throw new UnknownTokenTypeException($value); |
331 | } |
332 | |
333 | return $type; |
334 | } |
335 | } |
+ | Code Coverage |
+ |||||||||
+ | Lines |
+ Functions and Methods |
+ Classes and Traits |
+ |||||||
Total | +
+
+
+ |
+ 92.64% |
+ 151 / 163 |
+
+
+
+ |
+ 40.00% |
+ 2 / 5 |
+ CRAP | +
+
+
+ |
+ 0.00% |
+ 0 / 1 |
+
Parser | +
+
+
+ |
+ 92.64% |
+ 151 / 163 |
+
+
+
+ |
+ 40.00% |
+ 2 / 5 |
+ 58.30 | +
+
+
+ |
+ 0.00% |
+ 0 / 1 |
+
__construct | +
+
+
+ |
+ 100.00% |
+ 2 / 2 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ | ||
parse | +
+
+
+ |
+ 88.89% |
+ 8 / 9 |
+
+
+
+ |
+ 0.00% |
+ 0 / 1 |
+ 4.02 | ++ | ||
getExpression | +
+
+
+ |
+ 93.06% |
+ 134 / 144 |
+
+
+
+ |
+ 0.00% |
+ 0 / 1 |
+ 44.65 | ++ | ||
buildComposite | +
+
+
+ |
+ 83.33% |
+ 5 / 6 |
+
+
+
+ |
+ 0.00% |
+ 0 / 1 |
+ 7.23 | ++ | ||
getNextToken | +
+
+
+ |
+ 100.00% |
+ 2 / 2 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ |
1 | <?php |
2 | |
3 | declare(strict_types=1); |
4 | |
5 | namespace Symftony\Xpression; |
6 | |
7 | use Symftony\Xpression\Exception\Lexer\LexerException; |
8 | use Symftony\Xpression\Exception\Parser\ForbiddenTokenException; |
9 | use Symftony\Xpression\Exception\Parser\InvalidExpressionException; |
10 | use Symftony\Xpression\Exception\Parser\ParserException; |
11 | use Symftony\Xpression\Exception\Parser\UnexpectedTokenException; |
12 | use Symftony\Xpression\Exception\Parser\UnknownCompositeTypeException; |
13 | use Symftony\Xpression\Exception\Parser\UnsupportedTokenTypeException; |
14 | use Symftony\Xpression\Expr\ExpressionBuilderInterface; |
15 | |
16 | class Parser |
17 | { |
18 | /** |
19 | * @var int Keep the lexer current index |
20 | */ |
21 | public int $lexerIndex = 0; |
22 | |
23 | /** |
24 | * @var array|int[] |
25 | */ |
26 | protected array $precedence = [ |
27 | Lexer::T_AND => 15, |
28 | Lexer::T_NOT_AND => 14, |
29 | Lexer::T_OR => 10, |
30 | Lexer::T_XOR => 9, |
31 | Lexer::T_NOT_OR => 8, |
32 | ]; |
33 | |
34 | private Lexer $lexer; |
35 | |
36 | private ExpressionBuilderInterface $expressionBuilder; |
37 | |
38 | /** |
39 | * @var int Bitwise of all allowed operator. Default was Lexer::T_ALL |
40 | */ |
41 | private int $allowedTokenType; |
42 | |
43 | /** |
44 | * @var int bitwise of ExpressionBuilder supported operator |
45 | */ |
46 | private int $supportedTokenType; |
47 | |
48 | public function __construct(ExpressionBuilderInterface $expressionBuilder) |
49 | { |
50 | $this->lexer = new Lexer(); |
51 | $this->expressionBuilder = $expressionBuilder; |
52 | } |
53 | |
54 | /** |
55 | * @throws InvalidExpressionException |
56 | */ |
57 | public function parse(string $input, ?int $allowedTokenType = null): mixed |
58 | { |
59 | $this->allowedTokenType = null !== $allowedTokenType ? $allowedTokenType : Lexer::T_ALL; |
60 | $this->supportedTokenType = $this->expressionBuilder->getSupportedTokenType(); |
61 | |
62 | try { |
63 | $this->lexer->setInput($input); |
64 | $this->lexer->moveNext(); |
65 | |
66 | return $this->getExpression(); |
67 | } catch (LexerException $exception) { |
68 | throw new InvalidExpressionException($input, '', 0, $exception); |
69 | } catch (ParserException $exception) { |
70 | throw new InvalidExpressionException($input, '', 0, $exception); |
71 | } |
72 | } |
73 | |
74 | /** |
75 | * @throws ForbiddenTokenException |
76 | * @throws UnexpectedTokenException |
77 | * @throws UnsupportedTokenTypeException |
78 | */ |
79 | private function getExpression(mixed $previousExpression = null): mixed |
80 | { |
81 | $expression = $previousExpression ?: null; |
82 | $expectedTokenType = null !== $previousExpression ? Lexer::T_COMPOSITE : Lexer::T_OPEN_PARENTHESIS | Lexer::T_INPUT_PARAMETER; |
83 | $expressions = []; |
84 | $tokenPrecedence = null; |
85 | |
86 | $hasOpenParenthesis = false; |
87 | |
88 | $compositeOperator = null; |
89 | $contains = false; |
90 | $containsValue = null; |
91 | $comparisonFirstOperande = null; |
92 | $comparisonMultipleOperande = false; |
93 | $comparisonMethod = null; |
94 | |
95 | while ($currentToken = $this->getNextToken()) { |
96 | $currentTokenType = $currentToken['type']; |
97 | $currentTokenIndex = $this->lexerIndex; |
98 | ++$this->lexerIndex; |
99 | |
100 | if (!($this->supportedTokenType & $currentTokenType)) { |
101 | throw new UnsupportedTokenTypeException($currentToken, $this->lexer->getTokenSyntax($this->supportedTokenType)); |
102 | } |
103 | |
104 | if (!($this->allowedTokenType & $currentTokenType)) { |
105 | throw new ForbiddenTokenException($currentToken, $this->lexer->getTokenSyntax($this->allowedTokenType)); |
106 | } |
107 | |
108 | if (!($expectedTokenType & $currentTokenType)) { |
109 | throw new UnexpectedTokenException($currentToken, $this->lexer->getTokenSyntax($expectedTokenType)); |
110 | } |
111 | |
112 | switch ($currentTokenType) { |
113 | case Lexer::T_OPEN_PARENTHESIS: |
114 | $expression = $this->getExpression(); |
115 | $hasOpenParenthesis = true; |
116 | $expectedTokenType = Lexer::T_CLOSE_PARENTHESIS; |
117 | |
118 | break; |
119 | |
120 | case Lexer::T_CLOSE_PARENTHESIS: |
121 | if (!$hasOpenParenthesis) { |
122 | $this->lexerIndex = $currentTokenIndex; |
123 | $this->lexer->resetPosition($currentTokenIndex); |
124 | $this->lexer->moveNext(); |
125 | |
126 | break 2; |
127 | } |
128 | $hasOpenParenthesis = false; |
129 | $expectedTokenType = Lexer::T_COMPOSITE | Lexer::T_CLOSE_PARENTHESIS; |
130 | |
131 | break; |
132 | |
133 | case Lexer::T_COMMA: |
134 | $expectedTokenType = Lexer::T_OPERAND; |
135 | |
136 | break; |
137 | |
138 | case Lexer::T_INPUT_PARAMETER: |
139 | $currentTokenValue = $this->expressionBuilder->parameter($currentToken['value'], null !== $comparisonFirstOperande); |
140 | |
141 | // no break |
142 | case Lexer::T_STRING: |
143 | if (!isset($currentTokenValue)) { |
144 | $currentTokenValue = $this->expressionBuilder->string($currentToken['value']); |
145 | } |
146 | |
147 | // no break |
148 | case Lexer::T_INTEGER: |
149 | case Lexer::T_FLOAT: |
150 | if (!isset($currentTokenValue)) { |
151 | $currentTokenValue = $currentToken['value']; |
152 | } |
153 | if (null === $comparisonFirstOperande) { |
154 | $comparisonFirstOperande = $currentTokenValue; |
155 | $expectedTokenType = Lexer::T_COMPARISON; |
156 | $currentTokenValue = null; |
157 | |
158 | break; |
159 | } |
160 | |
161 | if (\is_array($comparisonMultipleOperande)) { |
162 | $comparisonMultipleOperande[] = $currentTokenValue; |
163 | $expectedTokenType = Lexer::T_COMMA | Lexer::T_CLOSE_SQUARE_BRACKET; |
164 | $currentTokenValue = null; |
165 | |
166 | break; |
167 | } |
168 | |
169 | if ($contains) { |
170 | $containsValue = $currentTokenValue; |
171 | $expectedTokenType = Lexer::T_DOUBLE_CLOSE_CURLY_BRACKET; |
172 | $currentTokenValue = null; |
173 | |
174 | break; |
175 | } |
176 | $expression = \call_user_func_array([$this->expressionBuilder, $comparisonMethod], [$comparisonFirstOperande, $currentTokenValue]); |
177 | $comparisonFirstOperande = null; |
178 | $comparisonMethod = null; |
179 | $currentTokenValue = null; |
180 | $expectedTokenType = Lexer::T_COMPOSITE | Lexer::T_CLOSE_PARENTHESIS; |
181 | |
182 | break; |
183 | |
184 | case Lexer::T_EQUALS: |
185 | $comparisonMethod = 'eq'; |
186 | $expectedTokenType = Lexer::T_OPERAND; |
187 | |
188 | break; |
189 | |
190 | case Lexer::T_NOT_EQUALS: |
191 | $comparisonMethod = 'neq'; |
192 | $expectedTokenType = Lexer::T_OPERAND; |
193 | |
194 | break; |
195 | |
196 | case Lexer::T_GREATER_THAN: |
197 | $comparisonMethod = 'gt'; |
198 | $expectedTokenType = Lexer::T_OPERAND; |
199 | |
200 | break; |
201 | |
202 | case Lexer::T_GREATER_THAN_EQUALS: |
203 | $comparisonMethod = 'gte'; |
204 | $expectedTokenType = Lexer::T_OPERAND; |
205 | |
206 | break; |
207 | |
208 | case Lexer::T_LOWER_THAN: |
209 | $comparisonMethod = 'lt'; |
210 | $expectedTokenType = Lexer::T_OPERAND; |
211 | |
212 | break; |
213 | |
214 | case Lexer::T_LOWER_THAN_EQUALS: |
215 | $comparisonMethod = 'lte'; |
216 | $expectedTokenType = Lexer::T_OPERAND; |
217 | |
218 | break; |
219 | |
220 | case Lexer::T_NOT_OPEN_SQUARE_BRACKET: |
221 | $comparisonMethod = 'notIn'; |
222 | $comparisonMultipleOperande = []; |
223 | $expectedTokenType = Lexer::T_OPERAND | Lexer::T_CLOSE_SQUARE_BRACKET; |
224 | |
225 | break; |
226 | |
227 | case Lexer::T_OPEN_SQUARE_BRACKET: |
228 | $comparisonMethod = 'in'; |
229 | $comparisonMultipleOperande = []; |
230 | $expectedTokenType = Lexer::T_OPERAND | Lexer::T_CLOSE_SQUARE_BRACKET; |
231 | |
232 | break; |
233 | |
234 | case Lexer::T_CLOSE_SQUARE_BRACKET: |
235 | $expression = \call_user_func_array([$this->expressionBuilder, $comparisonMethod], [$comparisonFirstOperande, $comparisonMultipleOperande]); |
236 | $comparisonMethod = null; |
237 | $comparisonFirstOperande = null; |
238 | $comparisonMultipleOperande = false; |
239 | $expectedTokenType = Lexer::T_COMPOSITE | Lexer::T_CLOSE_PARENTHESIS; |
240 | |
241 | break; |
242 | |
243 | case Lexer::T_DOUBLE_OPEN_CURLY_BRACKET: |
244 | $comparisonMethod = 'contains'; |
245 | $contains = true; |
246 | $expectedTokenType = Lexer::T_OPERAND | Lexer::T_DOUBLE_CLOSE_CURLY_BRACKET; |
247 | |
248 | break; |
249 | |
250 | case Lexer::T_NOT_DOUBLE_OPEN_CURLY_BRACKET: |
251 | $comparisonMethod = 'notContains'; |
252 | $contains = true; |
253 | $expectedTokenType = Lexer::T_OPERAND | Lexer::T_DOUBLE_CLOSE_CURLY_BRACKET; |
254 | |
255 | break; |
256 | |
257 | case Lexer::T_DOUBLE_CLOSE_CURLY_BRACKET: |
258 | $expression = \call_user_func_array([$this->expressionBuilder, $comparisonMethod], [$comparisonFirstOperande, $containsValue]); |
259 | $comparisonMethod = null; |
260 | $comparisonFirstOperande = null; |
261 | $contains = false; |
262 | $expectedTokenType = Lexer::T_COMPOSITE | Lexer::T_CLOSE_PARENTHESIS; |
263 | |
264 | break; |
265 | |
266 | case Lexer::T_AND: |
267 | case Lexer::T_NOT_AND: |
268 | case Lexer::T_OR: |
269 | case Lexer::T_NOT_OR: |
270 | case Lexer::T_XOR: |
271 | $currentTokenPrecedence = $this->precedence[$currentTokenType]; |
272 | if (null === $compositeOperator || $currentTokenType === $compositeOperator) { |
273 | $expressions[] = $expression; |
274 | $expression = null; |
275 | $compositeOperator = $currentTokenType; |
276 | $tokenPrecedence = $currentTokenPrecedence; |
277 | $expectedTokenType = Lexer::T_OPEN_PARENTHESIS | Lexer::T_INPUT_PARAMETER; |
278 | |
279 | break; |
280 | } |
281 | |
282 | if ($currentTokenPrecedence < $tokenPrecedence) { |
283 | $expressions[] = $expression; |
284 | $expression = null; |
285 | $expressions = [$this->buildComposite($compositeOperator, $expressions)]; |
286 | $compositeOperator = $currentTokenType; |
287 | $tokenPrecedence = $currentTokenPrecedence; |
288 | $expectedTokenType = Lexer::T_OPEN_PARENTHESIS | Lexer::T_INPUT_PARAMETER; |
289 | |
290 | break; |
291 | } |
292 | |
293 | if ($currentTokenPrecedence > $tokenPrecedence) { |
294 | $this->lexerIndex = $currentTokenIndex; |
295 | $this->lexer->resetPosition($currentTokenIndex); |
296 | $this->lexer->moveNext(); |
297 | $expression = $this->getExpression($expression); |
298 | |
299 | break; |
300 | } |
301 | |
302 | throw new \LogicException(sprintf( |
303 | 'Token precedence error. Current token precedence %s must be different than %s', |
304 | $currentTokenPrecedence, |
305 | $tokenPrecedence |
306 | )); |
307 | |
308 | default: |
309 | throw new \LogicException(sprintf( |
310 | 'Token mismatch. Expected token %s given %s', |
311 | $this->lexer->getLiteral($expectedTokenType), |
312 | $currentTokenType |
313 | )); |
314 | } |
315 | } |
316 | |
317 | if (null !== $expression) { |
318 | $expressions[] = $expression; |
319 | } |
320 | |
321 | if (1 === \count($expressions)) { |
322 | return $expressions[0]; |
323 | } |
324 | |
325 | return $this->buildComposite($compositeOperator, $expressions); |
326 | } |
327 | |
328 | /** |
329 | * @param mixed $type |
330 | * @param mixed $expressions |
331 | * |
332 | * @return mixed |
333 | * |
334 | * @throws UnknownCompositeTypeException |
335 | */ |
336 | private function buildComposite($type, $expressions) |
337 | { |
338 | switch ($type) { |
339 | case Lexer::T_AND: |
340 | return $this->expressionBuilder->andX($expressions); |
341 | |
342 | case Lexer::T_NOT_AND: |
343 | return $this->expressionBuilder->nandX($expressions); |
344 | |
345 | case Lexer::T_OR: |
346 | return $this->expressionBuilder->orX($expressions); |
347 | |
348 | case Lexer::T_NOT_OR: |
349 | return $this->expressionBuilder->norX($expressions); |
350 | |
351 | case Lexer::T_XOR: |
352 | return $this->expressionBuilder->xorX($expressions); |
353 | |
354 | default: |
355 | throw new UnknownCompositeTypeException($type); |
356 | } |
357 | } |
358 | |
359 | /** |
360 | * @return null|array |
361 | */ |
362 | private function getNextToken(): mixed |
363 | { |
364 | $this->lexer->moveNext(); |
365 | |
366 | return $this->lexer->token; |
367 | } |
368 | } |
+ | Code Coverage |
+ |||||||||
+ | Lines |
+ Functions and Methods |
+ Classes and Traits |
+ |||||||
Total | +
+
+
+ |
+ 100.00% |
+ 8 / 8 |
+
+
+
+ |
+ 100.00% |
+ 2 / 2 |
+ CRAP | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
QueryStringParser | +
+
+
+ |
+ 100.00% |
+ 8 / 8 |
+
+
+
+ |
+ 100.00% |
+ 2 / 2 |
+ 3 | +
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+
correctServerQueryString | +
+
+
+ |
+ 100.00% |
+ 3 / 3 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 2 | ++ | ||
encodeXpression | +
+
+
+ |
+ 100.00% |
+ 5 / 5 |
+
+
+
+ |
+ 100.00% |
+ 1 / 1 |
+ 1 | ++ |
1 | <?php |
2 | |
3 | declare(strict_types=1); |
4 | |
5 | namespace Symftony\Xpression; |
6 | |
7 | class QueryStringParser |
8 | { |
9 | public static function correctServerQueryString(): void |
10 | { |
11 | if (isset($_SERVER['QUERY_STRING'])) { |
12 | $_SERVER['QUERY_STRING'] = self::encodeXpression($_SERVER['QUERY_STRING']); |
13 | parse_str($_SERVER['QUERY_STRING'], $_GET); |
14 | } |
15 | } |
16 | |
17 | /** |
18 | * @return string |
19 | */ |
20 | public static function encodeXpression(string $queryString) |
21 | { |
22 | return preg_replace_callback( |
23 | '/(=)\{([^}]*(?:}}[^}]*)*)(?:(?:}(&))|(?:}$))/', |
24 | static fn ($matches) => $matches[1].urlencode($matches[2]).($matches[3] ?? ''), |
25 | urldecode($queryString) |
26 | ); |
27 | } |
28 | } |
0)for(u=-1;++u 0)for(u=-1;++u","
"],col:[2,"
"],tr:[2,"","
"],td:[3,"
"],_default:[0,"",""]};function ye(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?S.merge([e],n):n}function ve(e,t){for(var n=0,r=e.length;n"," ").append(S.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},S.expr.pseudos.animated=function(t){return S.grep(S.timers,function(e){return t===e.elem}).length},S.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=S.css(e,"position"),c=S(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=S.css(e,"top"),u=S.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,S.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},S.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){S.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===S.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===S.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=S(e).offset()).top+=S.css(e,"borderTopWidth",!0),i.left+=S.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-S.css(r,"marginTop",!0),left:t.left-i.left-S.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===S.css(e,"position"))e=e.offsetParent;return e||re})}}),S.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;S.fn[t]=function(e){return B(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),S.each(["top","left"],function(e,n){S.cssHooks[n]=_e(v.pixelPosition,function(e,t){if(t)return t=Be(e,n),Pe.test(t)?S(e).position()[n]+"px":t})}),S.each({Height:"height",Width:"width"},function(a,s){S.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){S.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return B(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?S.css(e,t,i):S.style(e,t,n,i)},s,n?e:void 0,n)}})}),S.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){S.fn[t]=function(e){return this.on(t,e)}}),S.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),S.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){S.fn[n]=function(e,t){return 0
"}),b},a.models.candlestickBarChart=function(){var b=a.models.historicalBarChart(a.models.candlestickBar());return b.useInteractiveGuideline(!0),b.interactiveLayer.tooltip.contentGenerator(function(a){var c=a.series[0].data,d=c.openopen: "+b.yAxis.tickFormat()(c.open)+" close: "+b.yAxis.tickFormat()(c.close)+" high "+b.yAxis.tickFormat()(c.high)+" low: "+b.yAxis.tickFormat()(c.low)+"
"}),b},a.models.legend=function(){"use strict";function b(p){function q(a,b){return"furious"!=o?"#000":m?a.disengaged?"#000":"#fff":m?void 0:(a.color||(a.color=g(a,b)),a.disabled?a.color:"#fff")}function r(a,b){return m&&"furious"==o&&a.disengaged?"#eee":a.color||g(a,b)}function s(a){return m&&"furious"==o?1:a.disabled?0:1}return p.each(function(b){var g=d-c.left-c.right,p=d3.select(this);a.utils.initSVG(p);var t=p.selectAll("g.nv-legend").data([b]),u=t.enter().append("g").attr("class","nvd3 nv-legend").append("g"),v=t.select("g");t.attr("transform","translate("+c.left+","+c.top+")");var w,x,y=v.selectAll(".nv-series").data(function(a){return"furious"!=o?a:a.filter(function(a){return m?!0:!a.disengaged})}),z=y.enter().append("g").attr("class","nv-series");switch(o){case"furious":x=23;break;case"classic":x=20}if("classic"==o)z.append("circle").style("stroke-width",2).attr("class","nv-legend-symbol").attr("r",5),w=y.select("circle");else if("furious"==o){z.append("rect").style("stroke-width",2).attr("class","nv-legend-symbol").attr("rx",3).attr("ry",3),w=y.select(".nv-legend-symbol"),z.append("g").attr("class","nv-check-box").property("innerHTML",'open: "+b.yAxis.tickFormat()(c.open)+" close: "+b.yAxis.tickFormat()(c.close)+" high "+b.yAxis.tickFormat()(c.high)+" low: "+b.yAxis.tickFormat()(c.low)+" s[c]&&(e.offsets.popper[m]+=d[m]+u-s[c]),e.offsets.popper=g(e.offsets.popper);var b=d[m]+d[l]/2-u/2,w=t(e.instance.popper),y=parseFloat(w['margin'+f]),E=parseFloat(w['border'+f+'Width']),v=b-e.offsets.popper[m]-y-E;return v=ee(Q(s[l]-u,v),0),e.arrowElement=i,e.offsets.arrow=(n={},ae(n,m,$(v)),ae(n,h,''),n),e},element:'[x-arrow]'},flip:{order:600,enabled:!0,fn:function(e,t){if(W(e.instance.modifiers,'inner'))return e;if(e.flipped&&e.placement===e.originalPlacement)return e;var o=v(e.instance.popper,e.instance.reference,t.padding,t.boundariesElement,e.positionFixed),n=e.placement.split('-')[0],i=T(n),r=e.placement.split('-')[1]||'',p=[];switch(t.behavior){case ce.FLIP:p=[n,i];break;case ce.CLOCKWISE:p=G(n);break;case ce.COUNTERCLOCKWISE:p=G(n,!0);break;default:p=t.behavior;}return p.forEach(function(s,d){if(n!==s||p.length===d+1)return e;n=e.placement.split('-')[0],i=T(n);var a=e.offsets.popper,l=e.offsets.reference,f=Z,m='left'===n&&f(a.right)>f(l.left)||'right'===n&&f(a.left)Classes
+ Coverage Distribution
+ Complexity
+ Insufficient Coverage
+
+
+
+
+
+
+
+
+
+ Class
+ Coverage
+ Project Risks
+
+
+
+
+
+
+
+
+
+ Class
+ CRAP
+ Methods
+ Coverage Distribution
+ Complexity
+ Insufficient Coverage
+
+
+
+
+
+
+
+ Method
+ Coverage
+
+ contains 66%
+ buildComposite 83%
+ mapField 87%
+
+
+ parse 88% Project Risks
+
+
+
+
+
+
+
+ Method
+ CRAP
+
+ buildComposite 7
+ mapField 6
+ parse 4
+
+
+ contains 2
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Total
+
+
+
+
+
+
+
+
+
+
+
+
+ Bridge
+
+
+
+
+
+
+
+
+
+
+
+
+ Expr
+
+
+
+
+
+
+
+
+
+
+
+
+ Lexer.php
+
+
+
+
+
+
+
+
+
+
+
+
+ Parser.php
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ QueryStringParser.php
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Total
+
+
+
+
+
+
+ CRAP
+
+
+
+
+
+
+ ExpressionBuilderAdapter
+
+
+
+
+
+
+ 21
+
+
+
+
+
+
+ __construct
+
+
+
+
+
+
+ 1
+
+
+
+
+ getSupportedTokenType
+
+
+
+
+
+
+ 1
+
+
+
+
+ parameter
+
+
+
+
+
+
+ 1
+
+
+
+
+ string
+
+
+
+
+
+
+ 1
+
+
+
+
+ isNull
+
+
+
+
+
+
+ 1
+
+
+
+
+ eq
+
+
+
+
+
+
+ 1
+
+
+
+
+ neq
+
+
+
+
+
+
+ 1
+
+
+
+
+ gt
+
+
+
+
+
+
+ 1
+
+
+
+
+ gte
+
+
+
+
+
+
+ 1
+
+
+
+
+ lt
+
+
+
+
+
+
+ 1
+
+
+
+
+ lte
+
+
+
+
+
+
+ 1
+
+
+
+
+ in
+
+
+
+
+
+
+ 1
+
+
+
+
+ notIn
+
+
+
+
+
+
+ 1
+
+
+
+
+ contains
+
+
+
+
+
+
+ 2.15
+
+
+
+
+ notContains
+
+
+
+
+
+
+ 1
+
+
+
+
+ andX
+
+
+
+
+
+
+ 1
+
+
+
+
+ nandX
+
+
+
+
+
+
+ 1
+
+
+
+
+ orX
+
+
+
+
+
+
+ 1
+
+
+
+
+ norX
+
+
+
+
+
+
+ 1
+
+
+
+
+
+
+ xorX
+
+
+
+
+
+
+ 1
+
+
+
+
+
+
+
+
+ 1 <?php
+ 2
+ 3 declare(strict_types=1);
+ 4
+ 5 namespace Symftony\Xpression\Bridge\Doctrine\Common;
+ 6
+ 7 use Doctrine\Common\Collections\ExpressionBuilder;
+ 8 use Symftony\Xpression\Exception\Expr\UnsupportedExpressionTypeException;
+ 9 use Symftony\Xpression\Expr\ExpressionBuilderInterface;
+ 10 use Symftony\Xpression\Lexer;
+ 11
+ 12 class ExpressionBuilderAdapter implements ExpressionBuilderInterface
+ 13 {
+ 14 public function __construct(
+ 15 private ExpressionBuilder $expressionBuilder
+ 16 ) {}
+ 17
+ 18 public function getSupportedTokenType(): int
+ 19 {
+ 20 return Lexer::T_ALL - Lexer::T_NOT_AND - Lexer::T_NOT_OR - Lexer::T_XOR - Lexer::T_NOT_DOUBLE_OPEN_CURLY_BRACKET;
+ 21 }
+ 22
+ 23 public function parameter(mixed $value, bool $isValue = false): mixed
+ 24 {
+ 25 return $value;
+ 26 }
+ 27
+ 28 public function string(mixed $value): mixed
+ 29 {
+ 30 return $value;
+ 31 }
+ 32
+ 33 public function isNull(string $field): mixed
+ 34 {
+ 35 return $this->expressionBuilder->isNull($field);
+ 36 }
+ 37
+ 38 public function eq(string $field, mixed $value): mixed
+ 39 {
+ 40 return $this->expressionBuilder->eq($field, $value);
+ 41 }
+ 42
+ 43 public function neq(string $field, mixed $value): mixed
+ 44 {
+ 45 return $this->expressionBuilder->neq($field, $value);
+ 46 }
+ 47
+ 48 public function gt(string $field, mixed $value): mixed
+ 49 {
+ 50 return $this->expressionBuilder->gt($field, $value);
+ 51 }
+ 52
+ 53 public function gte(string $field, mixed $value): mixed
+ 54 {
+ 55 return $this->expressionBuilder->gte($field, $value);
+ 56 }
+ 57
+ 58 public function lt(string $field, mixed $value): mixed
+ 59 {
+ 60 return $this->expressionBuilder->lt($field, $value);
+ 61 }
+ 62
+ 63 public function lte(string $field, mixed $value): mixed
+ 64 {
+ 65 return $this->expressionBuilder->lte($field, $value);
+ 66 }
+ 67
+ 68 public function in(string $field, array $values): mixed
+ 69 {
+ 70 return $this->expressionBuilder->in($field, $values);
+ 71 }
+ 72
+ 73 public function notIn(string $field, array $values): mixed
+ 74 {
+ 75 return $this->expressionBuilder->notIn($field, $values);
+ 76 }
+ 77
+ 78 /**
+ 79 * /!\ Contains operator appear only in doctrine/common v1.1 /!\.
+ 80 */
+ 81 public function contains(string $field, mixed $value): mixed
+ 82 {
+ 83 if (!method_exists($this->expressionBuilder, 'contains')) {
+ 84 throw new UnsupportedExpressionTypeException('contains');
+ 85 }
+ 86
+ 87 return $this->expressionBuilder->contains($field, $value);
+ 88 }
+ 89
+ 90 public function notContains(string $field, mixed $value): mixed
+ 91 {
+ 92 throw new UnsupportedExpressionTypeException('notContains');
+ 93 }
+ 94
+ 95 public function andX(array $expressions): mixed
+ 96 {
+ 97 return $this->expressionBuilder->andX(...$expressions);
+ 98 }
+ 99
+ 100 public function nandX(array $expressions): mixed
+ 101 {
+ 102 throw new UnsupportedExpressionTypeException('nandX');
+ 103 }
+ 104
+ 105 public function orX(array $expressions): mixed
+ 106 {
+ 107 return $this->expressionBuilder->orX(...$expressions);
+ 108 }
+ 109
+ 110 public function norX(array $expressions): mixed
+ 111 {
+ 112 throw new UnsupportedExpressionTypeException('norX');
+ 113 }
+ 114
+ 115 public function xorX(array $expressions): mixed
+ 116 {
+ 117 throw new UnsupportedExpressionTypeException('xorX');
+ 118 }
+
+
+119 } Classes
+ Coverage Distribution
+ Complexity
+ Insufficient Coverage
+
+
+
+
+
+
+
+
+
+ Class
+ Coverage
+ Project Risks
+
+
+
+
+
+
+
+
+
+ Class
+ CRAP
+ Methods
+ Coverage Distribution
+ Complexity
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Total
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ExpressionBuilderAdapter.php
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Total
+
+
+
+
+
+
+ CRAP
+
+
+
+
+
+
+ ExprAdapter
+
+
+
+
+
+
+ 21
+
+
+
+
+
+
+ __construct
+
+
+
+
+
+
+ 1
+
+
+
+
+ getSupportedTokenType
+
+
+
+
+
+
+ 1
+
+
+
+
+ parameter
+
+
+
+
+
+
+ 2
+
+
+
+
+ string
+
+
+
+
+
+
+ 1
+
+
+
+
+ isNull
+
+
+
+
+
+
+ 1
+
+
+
+
+ eq
+
+
+
+
+
+
+ 1
+
+
+
+
+ neq
+
+
+
+
+
+
+ 1
+
+
+
+
+ gt
+
+
+
+
+
+
+ 1
+
+
+
+
+ gte
+
+
+
+
+
+
+ 1
+
+
+
+
+ lt
+
+
+
+
+
+
+ 1
+
+
+
+
+ lte
+
+
+
+
+
+
+ 1
+
+
+
+
+ in
+
+
+
+
+
+
+ 1
+
+
+
+
+ notIn
+
+
+
+
+
+
+ 1
+
+
+
+
+ contains
+
+
+
+
+
+
+ 1
+
+
+
+
+ notContains
+
+
+
+
+
+
+ 1
+
+
+
+
+ andX
+
+
+
+
+
+
+ 1
+
+
+
+
+ nandX
+
+
+
+
+
+
+ 1
+
+
+
+
+ orX
+
+
+
+
+
+
+ 1
+
+
+
+
+ norX
+
+
+
+
+
+
+ 1
+
+
+
+
+
+
+ xorX
+
+
+
+
+
+
+ 1
+
+
+
+
+
+
+
+
+ 1 <?php
+ 2
+ 3 declare(strict_types=1);
+ 4
+ 5 namespace Symftony\Xpression\Bridge\Doctrine\ORM;
+ 6
+ 7 use Doctrine\ORM\Query\Expr;
+ 8 use Symftony\Xpression\Exception\Expr\UnsupportedExpressionTypeException;
+ 9 use Symftony\Xpression\Expr\ExpressionBuilderInterface;
+ 10 use Symftony\Xpression\Lexer;
+ 11
+ 12 class ExprAdapter implements ExpressionBuilderInterface
+ 13 {
+ 14 private Expr $expr;
+ 15
+ 16 public function __construct(Expr $expr)
+ 17 {
+ 18 $this->expr = $expr;
+ 19 }
+ 20
+ 21 public function getSupportedTokenType(): int
+ 22 {
+ 23 return Lexer::T_ALL - Lexer::T_NOT_AND - Lexer::T_NOT_OR - Lexer::T_XOR;
+ 24 }
+ 25
+ 26 public function parameter(mixed $value, bool $isValue = false): mixed
+ 27 {
+ 28 return $isValue ? $this->expr->literal($value) : $value;
+ 29 }
+ 30
+ 31 public function string(mixed $value): mixed
+ 32 {
+ 33 return $this->expr->literal($value);
+ 34 }
+ 35
+ 36 public function isNull(string $field): mixed
+ 37 {
+ 38 return $this->expr->isNull($field);
+ 39 }
+ 40
+ 41 public function eq(string $field, mixed $value): mixed
+ 42 {
+ 43 return $this->expr->eq($field, $value);
+ 44 }
+ 45
+ 46 public function neq(string $field, mixed $value): mixed
+ 47 {
+ 48 return $this->expr->neq($field, $value);
+ 49 }
+ 50
+ 51 public function gt(string $field, mixed $value): mixed
+ 52 {
+ 53 return $this->expr->gt($field, $value);
+ 54 }
+ 55
+ 56 public function gte(string $field, mixed $value): mixed
+ 57 {
+ 58 return $this->expr->gte($field, $value);
+ 59 }
+ 60
+ 61 public function lt(string $field, mixed $value): mixed
+ 62 {
+ 63 return $this->expr->lt($field, $value);
+ 64 }
+ 65
+ 66 public function lte(string $field, mixed $value): mixed
+ 67 {
+ 68 return $this->expr->lte($field, $value);
+ 69 }
+ 70
+ 71 public function in(string $field, array $values): mixed
+ 72 {
+ 73 return $this->expr->in($field, $values);
+ 74 }
+ 75
+ 76 public function notIn(string $field, array $values): mixed
+ 77 {
+ 78 return $this->expr->notIn($field, $values);
+ 79 }
+ 80
+ 81 public function contains(string $field, mixed $value): mixed
+ 82 {
+ 83 return $this->expr->like($field, $value);
+ 84 }
+ 85
+ 86 public function notContains(string $field, mixed $value): mixed
+ 87 {
+ 88 return $this->expr->notLike($field, $value);
+ 89 }
+ 90
+ 91 public function andX(array $expressions): mixed
+ 92 {
+ 93 return $this->expr->andX(...$expressions);
+ 94 }
+ 95
+ 96 public function nandX(array $expressions): mixed
+ 97 {
+ 98 throw new UnsupportedExpressionTypeException('nandX');
+ 99 }
+ 100
+ 101 public function orX(array $expressions): mixed
+ 102 {
+ 103 return $this->expr->orX(...$expressions);
+ 104 }
+ 105
+ 106 public function norX(array $expressions): mixed
+ 107 {
+ 108 throw new UnsupportedExpressionTypeException('norX');
+ 109 }
+ 110
+ 111 public function xorX(array $expressions): mixed
+ 112 {
+ 113 throw new UnsupportedExpressionTypeException('xorX');
+ 114 }
+
+
+115 } Classes
+ Coverage Distribution
+ Complexity
+ Insufficient Coverage
+
+
+
+
+
+
+
+
+
+ Class
+ Coverage
+ Project Risks
+
+
+
+
+
+
+
+
+
+ Class
+ CRAP
+ Methods
+ Coverage Distribution
+ Complexity
+ Insufficient Coverage
+
+
+
+
+
+
+
+
+
+ Method
+ Coverage
+ Project Risks
+
+
+
+
+
+
+
+
+
+ Method
+ CRAP
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Total
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ExprAdapter.php
+
+
+
+
+
+
+
+
+
+ Classes
+ Coverage Distribution
+ Complexity
+ Insufficient Coverage
+
+
+
+
+
+
+
+
+
+ Class
+ Coverage
+ Project Risks
+
+
+
+
+
+
+
+
+
+ Class
+ CRAP
+ Methods
+ Coverage Distribution
+ Complexity
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Total
+
+
+
+
+
+
+
+
+
+
+
+
+ Common
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ORM
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Total
+
+
+
+
+
+
+ CRAP
+
+
+
+
+
+
+ ExprBuilder
+
+
+
+
+
+
+ 19
+
+
+
+
+
+
+ getSupportedTokenType
+
+
+
+
+
+
+ 1
+
+
+
+
+ parameter
+
+
+
+
+
+
+ 1
+
+
+
+
+ string
+
+
+
+
+
+
+ 1
+
+
+
+
+ isNull
+
+
+
+
+
+
+ 1
+
+
+
+
+ eq
+
+
+
+
+
+
+ 1
+
+
+
+
+ neq
+
+
+
+
+
+
+ 1
+
+
+
+
+ gt
+
+
+
+
+
+
+ 1
+
+
+
+
+ gte
+
+
+
+
+
+
+ 1
+
+
+
+
+ lt
+
+
+
+
+
+
+ 1
+
+
+
+
+ lte
+
+
+
+
+
+
+ 1
+
+
+
+
+ in
+
+
+
+
+
+
+ 1
+
+
+
+
+ notIn
+
+
+
+
+
+
+ 1
+
+
+
+
+ contains
+
+
+
+
+
+
+ 1
+
+
+
+
+ notContains
+
+
+
+
+
+
+ 1
+
+
+
+
+ andX
+
+
+
+
+
+
+ 1
+
+
+
+
+ nandX
+
+
+
+
+
+
+ 1
+
+
+
+
+ orX
+
+
+
+
+
+
+ 1
+
+
+
+
+ norX
+
+
+
+
+
+
+ 1
+
+
+
+
+
+
+ xorX
+
+
+
+
+
+
+ 1
+
+
+
+
+
+
+
+
+ 1 <?php
+ 2
+ 3 declare(strict_types=1);
+ 4
+ 5 namespace Symftony\Xpression\Bridge\MongoDB;
+ 6
+ 7 use Symftony\Xpression\Exception\Expr\UnsupportedExpressionTypeException;
+ 8 use Symftony\Xpression\Expr\ExpressionBuilderInterface;
+ 9 use Symftony\Xpression\Lexer;
+ 10
+ 11 class ExprBuilder implements ExpressionBuilderInterface
+ 12 {
+ 13 public function getSupportedTokenType(): int
+ 14 {
+ 15 return Lexer::T_ALL - Lexer::T_XOR;
+ 16 }
+ 17
+ 18 public function parameter(mixed $value, bool $isValue = false): mixed
+ 19 {
+ 20 return $value;
+ 21 }
+ 22
+ 23 public function string(mixed $value): mixed
+ 24 {
+ 25 return $value;
+ 26 }
+ 27
+ 28 public function isNull(string $field): mixed
+ 29 {
+ 30 return [$field => null];
+ 31 }
+ 32
+ 33 public function eq(string $field, mixed $value): mixed
+ 34 {
+ 35 return [$field => ['$eq' => $value]];
+ 36 }
+ 37
+ 38 public function neq(string $field, mixed $value): mixed
+ 39 {
+ 40 return [$field => ['$ne' => $value]];
+ 41 }
+ 42
+ 43 public function gt(string $field, mixed $value): mixed
+ 44 {
+ 45 return [$field => ['$gt' => $value]];
+ 46 }
+ 47
+ 48 public function gte(string $field, mixed $value): mixed
+ 49 {
+ 50 return [$field => ['$gte' => $value]];
+ 51 }
+ 52
+ 53 public function lt(string $field, mixed $value): mixed
+ 54 {
+ 55 return [$field => ['$lt' => $value]];
+ 56 }
+ 57
+ 58 public function lte(string $field, mixed $value): mixed
+ 59 {
+ 60 return [$field => ['$lte' => $value]];
+ 61 }
+ 62
+ 63 public function in(string $field, array $values): mixed
+ 64 {
+ 65 return [$field => ['$in' => $values]];
+ 66 }
+ 67
+ 68 public function notIn(string $field, array $values): mixed
+ 69 {
+ 70 return [$field => ['$nin' => $values]];
+ 71 }
+ 72
+ 73 public function contains(string $field, mixed $value): mixed
+ 74 {
+ 75 return [$field => ['$regex' => $value]];
+ 76 }
+ 77
+ 78 public function notContains(string $field, mixed $value): mixed
+ 79 {
+ 80 return ['$not' => $this->contains($field, $value)];
+ 81 }
+ 82
+ 83 public function andX(array $expressions): mixed
+ 84 {
+ 85 return ['$and' => $expressions];
+ 86 }
+ 87
+ 88 // Not A AND B = Not A OR Not B
+ 89 public function nandX(array $expressions): mixed
+ 90 {
+ 91 return $this->orX(array_map(static fn ($expression) => ['$not' => $expression], $expressions));
+ 92 }
+ 93
+ 94 public function orX(array $expressions): mixed
+ 95 {
+ 96 return ['$or' => $expressions];
+ 97 }
+ 98
+ 99 public function norX(array $expressions): mixed
+ 100 {
+ 101 return ['$nor' => $expressions];
+ 102 }
+ 103
+ 104 public function xorX(array $expressions): mixed
+ 105 {
+ 106 throw new UnsupportedExpressionTypeException('xorX');
+ 107 }
+
+
+108 } Classes
+ Coverage Distribution
+ Complexity
+ Insufficient Coverage
+
+
+
+
+
+
+
+
+
+ Class
+ Coverage
+ Project Risks
+
+
+
+
+
+
+
+
+
+ Class
+ CRAP
+ Methods
+ Coverage Distribution
+ Complexity
+ Insufficient Coverage
+
+
+
+
+
+
+
+
+
+ Method
+ Coverage
+ Project Risks
+
+
+
+
+
+
+
+
+
+ Method
+ CRAP
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Total
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ExprBuilder.php
+
+
+
+
+
+
+
+
+
+ Classes
+ Coverage Distribution
+ Complexity
+ Insufficient Coverage
+
+
+
+
+
+
+
+
+
+ Class
+ Coverage
+ Project Risks
+
+
+
+
+
+
+
+
+
+ Class
+ CRAP
+ Methods
+ Coverage Distribution
+ Complexity
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Total
+
+
+
+
+
+
+
+
+
+
+
+
+ Doctrine
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ MongoDB
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Total
+
+
+
+
+
+
+ CRAP
+
+
+
+
+
+
+ ClosureExpressionBuilder
+
+
+
+
+
+
+ 34
+
+
+
+
+
+
+ getObjectFieldValue
+
+
+
+
+
+
+ 9.06
+
+
+
+
+ getSupportedTokenType
+
+
+
+
+
+
+ 1
+
+
+
+
+ parameter
+
+
+
+
+
+
+ 1
+
+
+
+
+ string
+
+
+
+
+
+
+ 1
+
+
+
+
+ isNull
+
+
+
+
+
+
+ 1
+
+
+
+
+ eq
+
+
+
+
+
+
+ 1
+
+
+
+
+ neq
+
+
+
+
+
+
+ 1
+
+
+
+
+ gt
+
+
+
+
+
+
+ 1
+
+
+
+
+ gte
+
+
+
+
+
+
+ 1
+
+
+
+
+ lt
+
+
+
+
+
+
+ 1
+
+
+
+
+ lte
+
+
+
+
+
+
+ 1
+
+
+
+
+ in
+
+
+
+
+
+
+ 1
+
+
+
+
+ notIn
+
+
+
+
+
+
+ 1
+
+
+
+
+ contains
+
+
+
+
+
+
+ 1
+
+
+
+
+ notContains
+
+
+
+
+
+
+ 1
+
+
+
+
+ andX
+
+
+
+
+
+
+ 3
+
+
+
+
+ nandX
+
+
+
+
+
+
+ 1
+
+
+
+
+ orX
+
+
+
+
+
+
+ 3
+
+
+
+
+ norX
+
+
+
+
+
+
+ 1
+
+
+
+
+
+
+ xorX
+
+
+
+
+
+
+ 3
+
+
+
+
+
+
+
+
+ 1 <?php
+ 2
+ 3 declare(strict_types=1);
+ 4
+ 5 namespace Symftony\Xpression\Expr;
+ 6
+ 7 use Symftony\Xpression\Lexer;
+ 8
+ 9 class ClosureExpressionBuilder implements ExpressionBuilderInterface
+ 10 {
+ 11 public static function getObjectFieldValue(mixed $object, mixed $field): mixed
+ 12 {
+ 13 if (\is_array($object)) {
+ 14 return $object[$field];
+ 15 }
+ 16
+ 17 $accessors = ['get', 'is'];
+ 18
+ 19 foreach ($accessors as $accessor) {
+ 20 $accessor .= $field;
+ 21
+ 22 if (!method_exists($object, $accessor)) {
+ 23 continue;
+ 24 }
+ 25
+ 26 return $object->{$accessor}();
+ 27 }
+ 28
+ 29 // __call should be triggered for get.
+ 30 $accessor = $accessors[0].$field;
+ 31
+ 32 if (method_exists($object, '__call')) {
+ 33 return $object->{$accessor}();
+ 34 }
+ 35
+ 36 if ($object instanceof \ArrayAccess) {
+ 37 return $object[$field];
+ 38 }
+ 39
+ 40 if (isset($object->{$field})) {
+ 41 return $object->{$field};
+ 42 }
+ 43
+ 44 // camelcase field name to support different variable naming conventions
+ 45 $ccField = preg_replace_callback('/_(.?)/', static fn ($matches) => strtoupper($matches[1]), $field);
+ 46
+ 47 foreach ($accessors as $accessor) {
+ 48 $accessor .= $ccField;
+ 49
+ 50 if (!method_exists($object, $accessor)) {
+ 51 continue;
+ 52 }
+ 53
+ 54 return $object->{$accessor}();
+ 55 }
+ 56
+ 57 return $object->{$field};
+ 58 }
+ 59
+ 60 public function getSupportedTokenType(): int
+ 61 {
+ 62 return Lexer::T_ALL;
+ 63 }
+ 64
+ 65 /**
+ 66 * @param bool $isValue
+ 67 * @param mixed $value
+ 68 */
+ 69 public function parameter($value, $isValue = false): mixed
+ 70 {
+ 71 return $value;
+ 72 }
+ 73
+ 74 public function string(mixed $value): mixed
+ 75 {
+ 76 return $value;
+ 77 }
+ 78
+ 79 public function isNull(string $field): mixed
+ 80 {
+ 81 return static fn ($object) => null === ClosureExpressionBuilder::getObjectFieldValue($object, $field);
+ 82 }
+ 83
+ 84 public function eq(string $field, mixed $value): mixed
+ 85 {
+ 86 return static fn ($object) => ClosureExpressionBuilder::getObjectFieldValue($object, $field) === $value;
+ 87 }
+ 88
+ 89 public function neq(string $field, mixed $value): mixed
+ 90 {
+ 91 return static fn ($object) => ClosureExpressionBuilder::getObjectFieldValue($object, $field) !== $value;
+ 92 }
+ 93
+ 94 public function gt(string $field, mixed $value): mixed
+ 95 {
+ 96 return static fn ($object) => ClosureExpressionBuilder::getObjectFieldValue($object, $field) > $value;
+ 97 }
+ 98
+ 99 public function gte(string $field, mixed $value): mixed
+ 100 {
+ 101 return static fn ($object) => ClosureExpressionBuilder::getObjectFieldValue($object, $field) >= $value;
+ 102 }
+ 103
+ 104 public function lt(string $field, mixed $value): mixed
+ 105 {
+ 106 return static fn ($object) => ClosureExpressionBuilder::getObjectFieldValue($object, $field) < $value;
+ 107 }
+ 108
+ 109 public function lte(string $field, mixed $value): mixed
+ 110 {
+ 111 return static fn ($object) => ClosureExpressionBuilder::getObjectFieldValue($object, $field) <= $value;
+ 112 }
+ 113
+ 114 public function in(string $field, array $values): mixed
+ 115 {
+ 116 return static fn ($object) => \in_array(ClosureExpressionBuilder::getObjectFieldValue($object, $field), $values, true);
+ 117 }
+ 118
+ 119 public function notIn(string $field, array $values): mixed
+ 120 {
+ 121 return static fn ($object) => !\in_array(ClosureExpressionBuilder::getObjectFieldValue($object, $field), $values, true);
+ 122 }
+ 123
+ 124 public function contains(string $field, mixed $value): mixed
+ 125 {
+ 126 return static fn ($object) => str_contains(ClosureExpressionBuilder::getObjectFieldValue($object, $field), $value);
+ 127 }
+ 128
+ 129 public function notContains(string $field, mixed $value): mixed
+ 130 {
+ 131 return static fn ($object) => !str_contains(ClosureExpressionBuilder::getObjectFieldValue($object, $field), $value);
+ 132 }
+ 133
+ 134 public function andX(array $expressions): mixed
+ 135 {
+ 136 return static function ($object) use ($expressions) {
+ 137 foreach ($expressions as $expression) {
+ 138 if (!$expression($object)) {
+ 139 return false;
+ 140 }
+ 141 }
+ 142
+ 143 return true;
+ 144 };
+ 145 }
+ 146
+ 147 public function nandX(array $expressions): mixed
+ 148 {
+ 149 $self = $this;
+ 150
+ 151 return static fn ($object) => !$self->andX($expressions)($object);
+ 152 }
+ 153
+ 154 public function orX(array $expressions): mixed
+ 155 {
+ 156 return static function ($object) use ($expressions) {
+ 157 foreach ($expressions as $expression) {
+ 158 if ($expression($object)) {
+ 159 return true;
+ 160 }
+ 161 }
+ 162
+ 163 return false;
+ 164 };
+ 165 }
+ 166
+ 167 public function norX(array $expressions): mixed
+ 168 {
+ 169 $self = $this;
+ 170
+ 171 return static fn ($object) => !$self->orX($expressions)($object);
+ 172 }
+ 173
+ 174 public function xorX(array $expressions): mixed
+ 175 {
+ 176 return static function ($object) use ($expressions) {
+ 177 $result = 0;
+ 178 foreach ($expressions as $expression) {
+ 179 if ($expression($object)) {
+ 180 ++$result;
+ 181 }
+ 182 }
+ 183
+ 184 $countExpressions = \count($expressions);
+ 185
+ 186 return 1 === $result | (2 < $countExpressions & $result === $countExpressions);
+ 187 };
+ 188 }
+
+
+189 }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Total
+
+
+
+
+
+
+ CRAP
+
+
+
+
+
+
+
+
+
+
+ 1 <?php
+ 2
+ 3 declare(strict_types=1);
+ 4
+ 5 namespace Symftony\Xpression\Expr;
+ 6
+ 7 interface ExpressionBuilderInterface
+ 8 {
+ 9 /**
+ 10 * Must return all supported token type.
+ 11 */
+ 12 public function getSupportedTokenType(): int;
+ 13
+ 14 public function parameter(mixed $value, bool $isValue = false): mixed;
+ 15
+ 16 public function string(mixed $value): mixed;
+ 17
+ 18 public function isNull(string $field): mixed;
+ 19
+ 20 public function eq(string $field, mixed $value): mixed;
+ 21
+ 22 public function neq(string $field, mixed $value): mixed;
+ 23
+ 24 public function gt(string $field, mixed $value): mixed;
+ 25
+ 26 public function gte(string $field, mixed $value): mixed;
+ 27
+ 28 public function lt(string $field, mixed $value): mixed;
+ 29
+ 30 public function lte(string $field, mixed $value): mixed;
+ 31
+ 32 public function in(string $field, array $values): mixed;
+ 33
+ 34 public function notIn(string $field, array $values): mixed;
+ 35
+ 36 public function contains(string $field, mixed $value): mixed;
+ 37
+ 38 public function notContains(string $field, mixed $value): mixed;
+ 39
+ 40 public function andX(array $expressions): mixed;
+ 41
+ 42 public function nandX(array $expressions): mixed;
+ 43
+ 44 public function orX(array $expressions): mixed;
+ 45
+ 46 public function norX(array $expressions): mixed;
+ 47
+ 48 public function xorX(array $expressions): mixed;
+
+
+49 }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Total
+
+
+
+
+
+
+ CRAP
+
+
+
+
+
+
+ HtmlExpressionBuilder
+
+
+
+
+
+
+ 22
+
+
+
+
+
+
+ __construct
+
+
+
+
+
+
+ 3
+
+
+
+
+ getSupportedTokenType
+
+
+
+
+
+
+ 1
+
+
+
+
+ parameter
+
+
+
+
+
+
+ 1
+
+
+
+
+ string
+
+
+
+
+
+
+ 1
+
+
+
+
+ isNull
+
+
+
+
+
+
+ 1
+
+
+
+
+ eq
+
+
+
+
+
+
+ 1
+
+
+
+
+ neq
+
+
+
+
+
+
+ 1
+
+
+
+
+ gt
+
+
+
+
+
+
+ 1
+
+
+
+
+ gte
+
+
+
+
+
+
+ 1
+
+
+
+
+ lt
+
+
+
+
+
+
+ 1
+
+
+
+
+ lte
+
+
+
+
+
+
+ 1
+
+
+
+
+ in
+
+
+
+
+
+
+ 1
+
+
+
+
+ notIn
+
+
+
+
+
+
+ 1
+
+
+
+
+ contains
+
+
+
+
+
+
+ 1
+
+
+
+
+ notContains
+
+
+
+
+
+
+ 1
+
+
+
+
+ andX
+
+
+
+
+
+
+ 1
+
+
+
+
+ nandX
+
+
+
+
+
+
+ 1
+
+
+
+
+ orX
+
+
+
+
+
+
+ 1
+
+
+
+
+ norX
+
+
+
+
+
+
+ 1
+
+
+
+
+
+
+ xorX
+
+
+
+
+
+
+ 1
+
+
+
+
+
+
+
+
+ 1 <?php
+ 2
+ 3 declare(strict_types=1);
+ 4
+ 5 namespace Symftony\Xpression\Expr;
+ 6
+ 7 use Symftony\Xpression\Lexer;
+ 8
+ 9 class HtmlExpressionBuilder implements ExpressionBuilderInterface
+ 10 {
+ 11 /**
+ 12 * This callable is use to delegate the html generation to a third party
+ 13 * eg: $comparisonHtmlBuilder($field, $operator, $value)
+ 14 * it must return the html code.
+ 15 *
+ 16 * @var callable
+ 17 */
+ 18 private $comparisonHtmlBuilder;
+ 19
+ 20 /**
+ 21 * This callable is use to delegate the html generation to a third party
+ 22 * eg: $compositeHtmlBuilder(array $expressions, $type)
+ 23 * it must return the html code.
+ 24 *
+ 25 * @var callable
+ 26 */
+ 27 private $compositeHtmlBuilder;
+ 28
+ 29 public function __construct(callable $comparisonHtmlBuilder = null, callable $compositeHtmlBuilder = null)
+ 30 {
+ 31 $this->comparisonHtmlBuilder = $comparisonHtmlBuilder ?: static fn ($field, $operator, $value) => sprintf('<div>%s %s %s</div>', $field, $operator, $value);
+ 32 $this->compositeHtmlBuilder = $compositeHtmlBuilder ?: static fn (array $expressions, $type) => str_replace(
+ 33 ['{type}', '{expressions}'],
+ 34 [$type, implode('', $expressions)],
+ 35 '<fieldset><legend>{type}</legend>{expressions}</fieldset>'
+ 36 );
+ 37 }
+ 38
+ 39 public function getSupportedTokenType(): int
+ 40 {
+ 41 return Lexer::T_ALL;
+ 42 }
+ 43
+ 44 public function parameter(mixed $value, bool $isValue = false): mixed
+ 45 {
+ 46 return $value;
+ 47 }
+ 48
+ 49 public function string(mixed $value): mixed
+ 50 {
+ 51 return '"'.$value.'"';
+ 52 }
+ 53
+ 54 public function isNull(string $field): mixed
+ 55 {
+ 56 return ($this->comparisonHtmlBuilder)($field, 'is', 'null');
+ 57 }
+ 58
+ 59 public function eq(string $field, mixed $value): mixed
+ 60 {
+ 61 return ($this->comparisonHtmlBuilder)($field, '=', $value);
+ 62 }
+ 63
+ 64 public function neq(string $field, mixed $value): mixed
+ 65 {
+ 66 return ($this->comparisonHtmlBuilder)($field, '≠', $value);
+ 67 }
+ 68
+ 69 public function gt(string $field, mixed $value): mixed
+ 70 {
+ 71 return ($this->comparisonHtmlBuilder)($field, '>', $value);
+ 72 }
+ 73
+ 74 public function gte(string $field, mixed $value): mixed
+ 75 {
+ 76 return ($this->comparisonHtmlBuilder)($field, '≥', $value);
+ 77 }
+ 78
+ 79 public function lt(string $field, mixed $value): mixed
+ 80 {
+ 81 return ($this->comparisonHtmlBuilder)($field, '<', $value);
+ 82 }
+ 83
+ 84 public function lte(string $field, mixed $value): mixed
+ 85 {
+ 86 return ($this->comparisonHtmlBuilder)($field, '≤', $value);
+ 87 }
+ 88
+ 89 public function in(string $field, array $values): mixed
+ 90 {
+ 91 return ($this->comparisonHtmlBuilder)($field, 'value in', implode(', ', $values));
+ 92 }
+ 93
+ 94 public function notIn(string $field, array $values): mixed
+ 95 {
+ 96 return ($this->comparisonHtmlBuilder)($field, 'value not in', implode(', ', $values));
+ 97 }
+ 98
+ 99 public function contains(string $field, mixed $value): mixed
+ 100 {
+ 101 return ($this->comparisonHtmlBuilder)($field, 'contains', $value);
+ 102 }
+ 103
+ 104 public function notContains(string $field, mixed $value): mixed
+ 105 {
+ 106 return ($this->comparisonHtmlBuilder)($field, 'notContains', $value);
+ 107 }
+ 108
+ 109 public function andX(array $expressions): mixed
+ 110 {
+ 111 return ($this->compositeHtmlBuilder)($expressions, 'and');
+ 112 }
+ 113
+ 114 public function nandX(array $expressions): mixed
+ 115 {
+ 116 return ($this->compositeHtmlBuilder)($expressions, 'not-and');
+ 117 }
+ 118
+ 119 public function orX(array $expressions): mixed
+ 120 {
+ 121 return ($this->compositeHtmlBuilder)($expressions, 'or');
+ 122 }
+ 123
+ 124 public function norX(array $expressions): mixed
+ 125 {
+ 126 return ($this->compositeHtmlBuilder)($expressions, 'not-or');
+ 127 }
+ 128
+ 129 public function xorX(array $expressions): mixed
+ 130 {
+ 131 return ($this->compositeHtmlBuilder)($expressions, 'exclusive-or');
+ 132 }
+
+
+133 }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Total
+
+
+
+
+
+
+ CRAP
+
+
+
+
+
+
+ MapperExpressionBuilder
+
+
+
+
+
+
+ 26
+
+
+
+
+
+
+ __construct
+
+
+
+
+
+
+ 1
+
+
+
+
+ getSupportedTokenType
+
+
+
+
+
+
+ 1
+
+
+
+
+ parameter
+
+
+
+
+
+
+ 1
+
+
+
+
+ string
+
+
+
+
+
+
+ 1
+
+
+
+
+ isNull
+
+
+
+
+
+
+ 1
+
+
+
+
+ eq
+
+
+
+
+
+
+ 1
+
+
+
+
+ neq
+
+
+
+
+
+
+ 1
+
+
+
+
+ gt
+
+
+
+
+
+
+ 1
+
+
+
+
+ gte
+
+
+
+
+
+
+ 1
+
+
+
+
+ lt
+
+
+
+
+
+
+ 1
+
+
+
+
+ lte
+
+
+
+
+
+
+ 1
+
+
+
+
+ in
+
+
+
+
+
+
+ 1
+
+
+
+
+ notIn
+
+
+
+
+
+
+ 1
+
+
+
+
+ contains
+
+
+
+
+
+
+ 1
+
+
+
+
+ notContains
+
+
+
+
+
+
+ 1
+
+
+
+
+ andX
+
+
+
+
+
+
+ 1
+
+
+
+
+ nandX
+
+
+
+
+
+
+ 1
+
+
+
+
+ orX
+
+
+
+
+
+
+ 1
+
+
+
+
+ norX
+
+
+
+
+
+
+ 1
+
+
+
+
+ xorX
+
+
+
+
+
+
+ 1
+
+
+
+
+
+
+ mapField
+
+
+
+
+
+
+ 6.07
+
+
+
+
+
+
+
+
+ 1 <?php
+ 2
+ 3 declare(strict_types=1);
+ 4
+ 5 namespace Symftony\Xpression\Expr;
+ 6
+ 7 class MapperExpressionBuilder implements ExpressionBuilderInterface
+ 8 {
+ 9 /**
+ 10 * @param string[] $fieldMapping
+ 11 */
+ 12 public function __construct(
+ 13 private ExpressionBuilderInterface $expressionBuilder,
+ 14 private array $fieldMapping = [],
+ 15 ) {}
+ 16
+ 17 public function getSupportedTokenType(): int
+ 18 {
+ 19 return $this->expressionBuilder->getSupportedTokenType();
+ 20 }
+ 21
+ 22 public function parameter(mixed $value, bool $isValue = false): mixed
+ 23 {
+ 24 return $this->expressionBuilder->parameter($value, $isValue);
+ 25 }
+ 26
+ 27 public function string(mixed $value): mixed
+ 28 {
+ 29 return $this->expressionBuilder->string($value);
+ 30 }
+ 31
+ 32 public function isNull(string $field): mixed
+ 33 {
+ 34 return $this->expressionBuilder->isNull($this->mapField($field));
+ 35 }
+ 36
+ 37 public function eq(string $field, mixed $value): mixed
+ 38 {
+ 39 return $this->expressionBuilder->eq($this->mapField($field), $value);
+ 40 }
+ 41
+ 42 public function neq(string $field, mixed $value): mixed
+ 43 {
+ 44 return $this->expressionBuilder->neq($this->mapField($field), $value);
+ 45 }
+ 46
+ 47 public function gt(string $field, mixed $value): mixed
+ 48 {
+ 49 return $this->expressionBuilder->gt($this->mapField($field), $value);
+ 50 }
+ 51
+ 52 public function gte(string $field, mixed $value): mixed
+ 53 {
+ 54 return $this->expressionBuilder->gte($this->mapField($field), $value);
+ 55 }
+ 56
+ 57 public function lt(string $field, mixed $value): mixed
+ 58 {
+ 59 return $this->expressionBuilder->lt($this->mapField($field), $value);
+ 60 }
+ 61
+ 62 public function lte(string $field, mixed $value): mixed
+ 63 {
+ 64 return $this->expressionBuilder->lte($this->mapField($field), $value);
+ 65 }
+ 66
+ 67 public function in(string $field, array $values): mixed
+ 68 {
+ 69 return $this->expressionBuilder->in($this->mapField($field), $values);
+ 70 }
+ 71
+ 72 public function notIn(string $field, array $values): mixed
+ 73 {
+ 74 return $this->expressionBuilder->notIn($this->mapField($field), $values);
+ 75 }
+ 76
+ 77 public function contains(string $field, mixed $value): mixed
+ 78 {
+ 79 return $this->expressionBuilder->contains($this->mapField($field), $value);
+ 80 }
+ 81
+ 82 public function notContains(string $field, mixed $value): mixed
+ 83 {
+ 84 return $this->expressionBuilder->notContains($this->mapField($field), $value);
+ 85 }
+ 86
+ 87 public function andX(array $expressions): mixed
+ 88 {
+ 89 return $this->expressionBuilder->andX($expressions);
+ 90 }
+ 91
+ 92 public function nandX(array $expressions): mixed
+ 93 {
+ 94 return $this->expressionBuilder->nandX($expressions);
+ 95 }
+ 96
+ 97 public function orX(array $expressions): mixed
+ 98 {
+ 99 return $this->expressionBuilder->orX($expressions);
+ 100 }
+ 101
+ 102 public function norX(array $expressions): mixed
+ 103 {
+ 104 return $this->expressionBuilder->norX($expressions);
+ 105 }
+ 106
+ 107 public function xorX(array $expressions): mixed
+ 108 {
+ 109 return $this->expressionBuilder->xorX($expressions);
+ 110 }
+ 111
+ 112 private function mapField(mixed $field): mixed
+ 113 {
+ 114 if (
+ 115 \is_array($field)
+ 116 || \is_object($field) && !method_exists($field, '__toString')
+ 117 ) {
+ 118 return $field;
+ 119 }
+ 120
+ 121 if (\array_key_exists((string) $field, $this->fieldMapping)) {
+ 122 return sprintf($this->fieldMapping[(string) $field], $field);
+ 123 }
+ 124
+ 125 if (\array_key_exists('*', $this->fieldMapping)) {
+ 126 return sprintf($this->fieldMapping['*'], $field);
+ 127 }
+ 128
+ 129 return $field;
+ 130 }
+
+
+131 } Classes
+ Coverage Distribution
+ Complexity
+ Insufficient Coverage
+
+
+
+
+
+
+
+
+
+ Class
+ Coverage
+ Project Risks
+
+
+
+
+
+
+
+
+
+ Class
+ CRAP
+ Methods
+ Coverage Distribution
+ Complexity
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Total
+
+
+
+
+
+
+
+
+
+
+
+
+ ClosureExpressionBuilder.php
+
+
+
+
+
+
+
+
+
+
+
+
+ ExpressionBuilderInterface.php
+
+
+
+
+
+
+
+
+
+
+
+
+ HtmlExpressionBuilder.php
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ MapperExpressionBuilder.php
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Total
+
+
+
+
+
+
+ CRAP
+
+
+
+
+
+
+ Lexer
+
+
+
+
+
+
+ 59
+
+
+
+
+
+
+ getTokenSyntax
+
+
+
+
+
+
+ 25
+
+
+
+
+ getCatchablePatterns
+
+
+
+
+
+
+ 1
+
+
+
+
+ getNonCatchablePatterns
+
+
+
+
+
+
+ 1
+
+
+
+
+
+
+ getType
+
+
+
+
+
+
+ 32
+
+
+
+
+
+
+
+
+ 1 <?php
+ 2
+ 3 declare(strict_types=1);
+ 4
+ 5 namespace Symftony\Xpression;
+ 6
+ 7 use Doctrine\Common\Lexer\AbstractLexer;
+ 8 use Symftony\Xpression\Exception\Lexer\UnknownTokenTypeException;
+ 9
+ 10 class Lexer extends AbstractLexer
+ 11 {
+ 12 public const T_NONE = 0;
+ 13 public const T_ALL = 2 ** 24 - 1;
+ 14
+ 15 // Punctuation
+ 16 public const T_COMMA = 2 ** 0;
+ 17
+ 18 // Operand
+ 19 public const T_OPERAND = 2 ** 1 + 2 ** 2 + 2 ** 3 + 2 ** 4;
+ 20 public const T_INTEGER = 2 ** 1;
+ 21 public const T_STRING = 2 ** 2;
+ 22 public const T_INPUT_PARAMETER = 2 ** 3;
+ 23 public const T_FLOAT = 2 ** 4;
+ 24
+ 25 // Comparison operator
+ 26 public const T_COMPARISON = 2 ** 5 + 2 ** 6 + 2 ** 7 + 2 ** 8 + 2 ** 9 + 2 ** 10 + 2 ** 18 + 2 ** 19 + 2 ** 21 + 2 ** 22;
+ 27 public const T_EQUALS = 2 ** 5;
+ 28 public const T_NOT_EQUALS = 2 ** 6;
+ 29 public const T_GREATER_THAN = 2 ** 7;
+ 30 public const T_GREATER_THAN_EQUALS = 2 ** 8;
+ 31 public const T_LOWER_THAN = 2 ** 9;
+ 32 public const T_LOWER_THAN_EQUALS = 2 ** 10;
+ 33
+ 34 // Composite operator
+ 35 public const T_COMPOSITE = 2 ** 11 + 2 ** 12 + 2 ** 13 + 2 ** 14 + 2 ** 15;
+ 36 public const T_AND = 2 ** 11;
+ 37 public const T_NOT_AND = 2 ** 12;
+ 38 public const T_OR = 2 ** 13;
+ 39 public const T_NOT_OR = 2 ** 14;
+ 40 public const T_XOR = 2 ** 15;
+ 41
+ 42 // Brace
+ 43 public const T_OPEN_PARENTHESIS = 2 ** 16;
+ 44 public const T_CLOSE_PARENTHESIS = 2 ** 17;
+ 45 public const T_OPEN_SQUARE_BRACKET = 2 ** 18;
+ 46 public const T_NOT_OPEN_SQUARE_BRACKET = 2 ** 19;
+ 47 public const T_CLOSE_SQUARE_BRACKET = 2 ** 20;
+ 48 public const T_DOUBLE_OPEN_CURLY_BRACKET = 2 ** 21;
+ 49 public const T_NOT_DOUBLE_OPEN_CURLY_BRACKET = 2 ** 22;
+ 50 public const T_DOUBLE_CLOSE_CURLY_BRACKET = 2 ** 23;
+ 51
+ 52 /**
+ 53 * @return string[]
+ 54 */
+ 55 public static function getTokenSyntax(mixed $tokenType): array
+ 56 {
+ 57 $tokenSyntax = [];
+ 58 // Punctuation
+ 59 if ($tokenType & self::T_COMMA) {
+ 60 $tokenSyntax[] = ',';
+ 61 }
+ 62
+ 63 // Recognize numeric values
+ 64 if ($tokenType & self::T_FLOAT) {
+ 65 $tokenSyntax[] = 'simple float';
+ 66 }
+ 67 if ($tokenType & self::T_INTEGER) {
+ 68 $tokenSyntax[] = 'simple integer';
+ 69 }
+ 70 if ($tokenType & self::T_INPUT_PARAMETER) {
+ 71 $tokenSyntax[] = '/[a-z_][a-z0-9_]*/';
+ 72 }
+ 73
+ 74 // Recognize quoted strings
+ 75 if ($tokenType & self::T_STRING) {
+ 76 $tokenSyntax[] = '"value" or \'value\'';
+ 77 }
+ 78
+ 79 // Comparison operator
+ 80 if ($tokenType & self::T_EQUALS) {
+ 81 $tokenSyntax[] = '=';
+ 82 }
+ 83 if ($tokenType & self::T_NOT_EQUALS) {
+ 84 $tokenSyntax[] = '≠or !=';
+ 85 }
+ 86 if ($tokenType & self::T_GREATER_THAN) {
+ 87 $tokenSyntax[] = '>';
+ 88 }
+ 89 if ($tokenType & self::T_GREATER_THAN_EQUALS) {
+ 90 $tokenSyntax[] = '≥ or >=';
+ 91 }
+ 92 if ($tokenType & self::T_LOWER_THAN) {
+ 93 $tokenSyntax[] = '<';
+ 94 }
+ 95 if ($tokenType & self::T_LOWER_THAN_EQUALS) {
+ 96 $tokenSyntax[] = '≤ or <=';
+ 97 }
+ 98
+ 99 // Composite operator
+ 100 if ($tokenType & self::T_AND) {
+ 101 $tokenSyntax[] = '&';
+ 102 }
+ 103 if ($tokenType & self::T_NOT_AND) {
+ 104 $tokenSyntax[] = '!&';
+ 105 }
+ 106 if ($tokenType & self::T_OR) {
+ 107 $tokenSyntax[] = '|';
+ 108 }
+ 109 if ($tokenType & self::T_NOT_OR) {
+ 110 $tokenSyntax[] = '!|';
+ 111 }
+ 112 if ($tokenType & self::T_XOR) {
+ 113 $tokenSyntax[] = '⊕ or ^|';
+ 114 }
+ 115
+ 116 // Brace
+ 117 if ($tokenType & self::T_OPEN_PARENTHESIS) {
+ 118 $tokenSyntax[] = '(';
+ 119 }
+ 120 if ($tokenType & self::T_CLOSE_PARENTHESIS) {
+ 121 $tokenSyntax[] = ')';
+ 122 }
+ 123 if ($tokenType & self::T_OPEN_SQUARE_BRACKET) {
+ 124 $tokenSyntax[] = '[';
+ 125 }
+ 126 if ($tokenType & self::T_NOT_OPEN_SQUARE_BRACKET) {
+ 127 $tokenSyntax[] = '![';
+ 128 }
+ 129 if ($tokenType & self::T_CLOSE_SQUARE_BRACKET) {
+ 130 $tokenSyntax[] = ']';
+ 131 }
+ 132 if ($tokenType & self::T_DOUBLE_OPEN_CURLY_BRACKET) {
+ 133 $tokenSyntax[] = '{{';
+ 134 }
+ 135 if ($tokenType & self::T_NOT_DOUBLE_OPEN_CURLY_BRACKET) {
+ 136 $tokenSyntax[] = '!{{';
+ 137 }
+ 138 if ($tokenType & self::T_DOUBLE_CLOSE_CURLY_BRACKET) {
+ 139 $tokenSyntax[] = '}}';
+ 140 }
+ 141
+ 142 return $tokenSyntax;
+ 143 }
+ 144
+ 145 /**
+ 146 * @return array
+ 147 */
+ 148 protected function getCatchablePatterns()
+ 149 {
+ 150 return [
+ 151 "'(?:[^']|'')*'", // quoted strings
+ 152 '"(?:[^"]|"")*"', // quoted strings
+ 153 '\^\||⊕|!&|&|!\||\|', // Composite operator
+ 154 '≤|≥|≠|<=|>=|!=|<|>|=|\[|!\[|\]|!{{|{{|}}', // Comparison operator
+ 155 '[a-z_][a-z0-9_\.\-]*', // identifier or qualified name
+ 156 '(?:[+-]?[0-9]*(?:[\.][0-9]+)*)', // numbers
+ 157 // '(?:[+-]?(?:(?:(?:[0-9]+|(?:[0-9]*[\.][0-9]+)|(?:[0-9]+[\.][0-9]*))[eE][+-]?[0-9]+)|(?:[0-9]*[\.][0-9]+)|(?:[0-9]+[\.][0-9]*)))', // number extended all float (.5 / 1.5 / -1.2e3)
+ 158 ];
+ 159 }
+ 160
+ 161 /**
+ 162 * @return array
+ 163 */
+ 164 protected function getNonCatchablePatterns()
+ 165 {
+ 166 return [
+ 167 '\s+',
+ 168 '(.)',
+ 169 ];
+ 170 }
+ 171
+ 172 /**
+ 173 * @param string $value
+ 174 *
+ 175 * @return int
+ 176 *
+ 177 * @throws UnknownTokenTypeException
+ 178 */
+ 179 protected function getType(&$value)
+ 180 {
+ 181 switch (true) {
+ 182 // Punctuation
+ 183 case ',' === $value[0]:
+ 184 $type = self::T_COMMA;
+ 185
+ 186 break;
+ 187
+ 188 // Recognize numeric values
+ 189 case is_numeric($value):
+ 190 if (str_contains($value, '.') || false !== stripos($value, 'e')) {
+ 191 $value = (float)$value;
+ 192 $type = self::T_FLOAT;
+ 193
+ 194 break;
+ 195 }
+ 196
+ 197 $value = (int)$value;
+ 198 $type = self::T_INTEGER;
+ 199
+ 200 break;
+ 201
+ 202 // Recognize quoted strings
+ 203 case '"' === $value[0]:
+ 204 $value = str_replace('""', '"', substr($value, 1, \strlen($value) - 2));
+ 205
+ 206 $type = self::T_STRING;
+ 207
+ 208 break;
+ 209
+ 210 case "'" === $value[0]:
+ 211 $value = str_replace("''", "'", substr($value, 1, \strlen($value) - 2));
+ 212
+ 213 $type = self::T_STRING;
+ 214
+ 215 break;
+ 216
+ 217 case preg_match('/[a-z_][a-z0-9_]*/i', $value):
+ 218 $type = self::T_INPUT_PARAMETER;
+ 219
+ 220 break;
+ 221
+ 222 // Comparison operator
+ 223 case '=' === $value:
+ 224 $type = self::T_EQUALS;
+ 225
+ 226 break;
+ 227
+ 228 case '≠' === $value:
+ 229 case '!=' === $value:
+ 230 $value = '≠';
+ 231 $type = self::T_NOT_EQUALS;
+ 232
+ 233 break;
+ 234
+ 235 case '>' === $value:
+ 236 $type = self::T_GREATER_THAN;
+ 237
+ 238 break;
+ 239
+ 240 case '>=' === $value:
+ 241 case '≥' === $value:
+ 242 $value = '≥';
+ 243 $type = self::T_GREATER_THAN_EQUALS;
+ 244
+ 245 break;
+ 246
+ 247 case '<' === $value:
+ 248 $type = self::T_LOWER_THAN;
+ 249
+ 250 break;
+ 251
+ 252 case '<=' === $value:
+ 253 case '≤' === $value:
+ 254 $value = '≤';
+ 255 $type = self::T_LOWER_THAN_EQUALS;
+ 256
+ 257 break;
+ 258
+ 259 // Composite operator
+ 260 case '&' === $value:
+ 261 $type = self::T_AND;
+ 262
+ 263 break;
+ 264
+ 265 case '!&' === $value:
+ 266 $type = self::T_NOT_AND;
+ 267
+ 268 break;
+ 269
+ 270 case '|' === $value:
+ 271 $type = self::T_OR;
+ 272
+ 273 break;
+ 274
+ 275 case '!|' === $value:
+ 276 $type = self::T_NOT_OR;
+ 277
+ 278 break;
+ 279
+ 280 case '^|' === $value:
+ 281 case '⊕' === $value:
+ 282 $value = '⊕';
+ 283 $type = self::T_XOR;
+ 284
+ 285 break;
+ 286
+ 287 // Brace
+ 288 case '(' === $value:
+ 289 $type = self::T_OPEN_PARENTHESIS;
+ 290
+ 291 break;
+ 292
+ 293 case ')' === $value:
+ 294 $type = self::T_CLOSE_PARENTHESIS;
+ 295
+ 296 break;
+ 297
+ 298 case '[' === $value:
+ 299 $type = self::T_OPEN_SQUARE_BRACKET;
+ 300
+ 301 break;
+ 302
+ 303 case '![' === $value:
+ 304 $type = self::T_NOT_OPEN_SQUARE_BRACKET;
+ 305
+ 306 break;
+ 307
+ 308 case ']' === $value:
+ 309 $type = self::T_CLOSE_SQUARE_BRACKET;
+ 310
+ 311 break;
+ 312
+ 313 case '{{' === $value:
+ 314 $type = self::T_DOUBLE_OPEN_CURLY_BRACKET;
+ 315
+ 316 break;
+ 317
+ 318 case '!{{' === $value:
+ 319 $type = self::T_NOT_DOUBLE_OPEN_CURLY_BRACKET;
+ 320
+ 321 break;
+ 322
+ 323 case '}}' === $value:
+ 324 $type = self::T_DOUBLE_CLOSE_CURLY_BRACKET;
+ 325
+ 326 break;
+ 327
+ 328 // Default
+ 329 default:
+ 330 throw new UnknownTokenTypeException($value);
+ 331 }
+ 332
+ 333 return $type;
+ 334 }
+
+
+335 }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Total
+
+
+
+
+
+
+ CRAP
+
+
+
+
+
+
+ Parser
+
+
+
+
+
+
+ 58.30
+
+
+
+
+
+
+ __construct
+
+
+
+
+
+
+ 1
+
+
+
+
+ parse
+
+
+
+
+
+
+ 4.02
+
+
+
+
+ getExpression
+
+
+
+
+
+
+ 44.65
+
+
+
+
+ buildComposite
+
+
+
+
+
+
+ 7.23
+
+
+
+
+
+
+ getNextToken
+
+
+
+
+
+
+ 1
+
+
+
+
+
+
+
+
+ 1 <?php
+ 2
+ 3 declare(strict_types=1);
+ 4
+ 5 namespace Symftony\Xpression;
+ 6
+ 7 use Symftony\Xpression\Exception\Lexer\LexerException;
+ 8 use Symftony\Xpression\Exception\Parser\ForbiddenTokenException;
+ 9 use Symftony\Xpression\Exception\Parser\InvalidExpressionException;
+ 10 use Symftony\Xpression\Exception\Parser\ParserException;
+ 11 use Symftony\Xpression\Exception\Parser\UnexpectedTokenException;
+ 12 use Symftony\Xpression\Exception\Parser\UnknownCompositeTypeException;
+ 13 use Symftony\Xpression\Exception\Parser\UnsupportedTokenTypeException;
+ 14 use Symftony\Xpression\Expr\ExpressionBuilderInterface;
+ 15
+ 16 class Parser
+ 17 {
+ 18 /**
+ 19 * @var int Keep the lexer current index
+ 20 */
+ 21 public int $lexerIndex = 0;
+ 22
+ 23 /**
+ 24 * @var array|int[]
+ 25 */
+ 26 protected array $precedence = [
+ 27 Lexer::T_AND => 15,
+ 28 Lexer::T_NOT_AND => 14,
+ 29 Lexer::T_OR => 10,
+ 30 Lexer::T_XOR => 9,
+ 31 Lexer::T_NOT_OR => 8,
+ 32 ];
+ 33
+ 34 private Lexer $lexer;
+ 35
+ 36 private ExpressionBuilderInterface $expressionBuilder;
+ 37
+ 38 /**
+ 39 * @var int Bitwise of all allowed operator. Default was Lexer::T_ALL
+ 40 */
+ 41 private int $allowedTokenType;
+ 42
+ 43 /**
+ 44 * @var int bitwise of ExpressionBuilder supported operator
+ 45 */
+ 46 private int $supportedTokenType;
+ 47
+ 48 public function __construct(ExpressionBuilderInterface $expressionBuilder)
+ 49 {
+ 50 $this->lexer = new Lexer();
+ 51 $this->expressionBuilder = $expressionBuilder;
+ 52 }
+ 53
+ 54 /**
+ 55 * @throws InvalidExpressionException
+ 56 */
+ 57 public function parse(string $input, ?int $allowedTokenType = null): mixed
+ 58 {
+ 59 $this->allowedTokenType = null !== $allowedTokenType ? $allowedTokenType : Lexer::T_ALL;
+ 60 $this->supportedTokenType = $this->expressionBuilder->getSupportedTokenType();
+ 61
+ 62 try {
+ 63 $this->lexer->setInput($input);
+ 64 $this->lexer->moveNext();
+ 65
+ 66 return $this->getExpression();
+ 67 } catch (LexerException $exception) {
+ 68 throw new InvalidExpressionException($input, '', 0, $exception);
+ 69 } catch (ParserException $exception) {
+ 70 throw new InvalidExpressionException($input, '', 0, $exception);
+ 71 }
+ 72 }
+ 73
+ 74 /**
+ 75 * @throws ForbiddenTokenException
+ 76 * @throws UnexpectedTokenException
+ 77 * @throws UnsupportedTokenTypeException
+ 78 */
+ 79 private function getExpression(mixed $previousExpression = null): mixed
+ 80 {
+ 81 $expression = $previousExpression ?: null;
+ 82 $expectedTokenType = null !== $previousExpression ? Lexer::T_COMPOSITE : Lexer::T_OPEN_PARENTHESIS | Lexer::T_INPUT_PARAMETER;
+ 83 $expressions = [];
+ 84 $tokenPrecedence = null;
+ 85
+ 86 $hasOpenParenthesis = false;
+ 87
+ 88 $compositeOperator = null;
+ 89 $contains = false;
+ 90 $containsValue = null;
+ 91 $comparisonFirstOperande = null;
+ 92 $comparisonMultipleOperande = false;
+ 93 $comparisonMethod = null;
+ 94
+ 95 while ($currentToken = $this->getNextToken()) {
+ 96 $currentTokenType = $currentToken['type'];
+ 97 $currentTokenIndex = $this->lexerIndex;
+ 98 ++$this->lexerIndex;
+ 99
+ 100 if (!($this->supportedTokenType & $currentTokenType)) {
+ 101 throw new UnsupportedTokenTypeException($currentToken, $this->lexer->getTokenSyntax($this->supportedTokenType));
+ 102 }
+ 103
+ 104 if (!($this->allowedTokenType & $currentTokenType)) {
+ 105 throw new ForbiddenTokenException($currentToken, $this->lexer->getTokenSyntax($this->allowedTokenType));
+ 106 }
+ 107
+ 108 if (!($expectedTokenType & $currentTokenType)) {
+ 109 throw new UnexpectedTokenException($currentToken, $this->lexer->getTokenSyntax($expectedTokenType));
+ 110 }
+ 111
+ 112 switch ($currentTokenType) {
+ 113 case Lexer::T_OPEN_PARENTHESIS:
+ 114 $expression = $this->getExpression();
+ 115 $hasOpenParenthesis = true;
+ 116 $expectedTokenType = Lexer::T_CLOSE_PARENTHESIS;
+ 117
+ 118 break;
+ 119
+ 120 case Lexer::T_CLOSE_PARENTHESIS:
+ 121 if (!$hasOpenParenthesis) {
+ 122 $this->lexerIndex = $currentTokenIndex;
+ 123 $this->lexer->resetPosition($currentTokenIndex);
+ 124 $this->lexer->moveNext();
+ 125
+ 126 break 2;
+ 127 }
+ 128 $hasOpenParenthesis = false;
+ 129 $expectedTokenType = Lexer::T_COMPOSITE | Lexer::T_CLOSE_PARENTHESIS;
+ 130
+ 131 break;
+ 132
+ 133 case Lexer::T_COMMA:
+ 134 $expectedTokenType = Lexer::T_OPERAND;
+ 135
+ 136 break;
+ 137
+ 138 case Lexer::T_INPUT_PARAMETER:
+ 139 $currentTokenValue = $this->expressionBuilder->parameter($currentToken['value'], null !== $comparisonFirstOperande);
+ 140
+ 141 // no break
+ 142 case Lexer::T_STRING:
+ 143 if (!isset($currentTokenValue)) {
+ 144 $currentTokenValue = $this->expressionBuilder->string($currentToken['value']);
+ 145 }
+ 146
+ 147 // no break
+ 148 case Lexer::T_INTEGER:
+ 149 case Lexer::T_FLOAT:
+ 150 if (!isset($currentTokenValue)) {
+ 151 $currentTokenValue = $currentToken['value'];
+ 152 }
+ 153 if (null === $comparisonFirstOperande) {
+ 154 $comparisonFirstOperande = $currentTokenValue;
+ 155 $expectedTokenType = Lexer::T_COMPARISON;
+ 156 $currentTokenValue = null;
+ 157
+ 158 break;
+ 159 }
+ 160
+ 161 if (\is_array($comparisonMultipleOperande)) {
+ 162 $comparisonMultipleOperande[] = $currentTokenValue;
+ 163 $expectedTokenType = Lexer::T_COMMA | Lexer::T_CLOSE_SQUARE_BRACKET;
+ 164 $currentTokenValue = null;
+ 165
+ 166 break;
+ 167 }
+ 168
+ 169 if ($contains) {
+ 170 $containsValue = $currentTokenValue;
+ 171 $expectedTokenType = Lexer::T_DOUBLE_CLOSE_CURLY_BRACKET;
+ 172 $currentTokenValue = null;
+ 173
+ 174 break;
+ 175 }
+ 176 $expression = \call_user_func_array([$this->expressionBuilder, $comparisonMethod], [$comparisonFirstOperande, $currentTokenValue]);
+ 177 $comparisonFirstOperande = null;
+ 178 $comparisonMethod = null;
+ 179 $currentTokenValue = null;
+ 180 $expectedTokenType = Lexer::T_COMPOSITE | Lexer::T_CLOSE_PARENTHESIS;
+ 181
+ 182 break;
+ 183
+ 184 case Lexer::T_EQUALS:
+ 185 $comparisonMethod = 'eq';
+ 186 $expectedTokenType = Lexer::T_OPERAND;
+ 187
+ 188 break;
+ 189
+ 190 case Lexer::T_NOT_EQUALS:
+ 191 $comparisonMethod = 'neq';
+ 192 $expectedTokenType = Lexer::T_OPERAND;
+ 193
+ 194 break;
+ 195
+ 196 case Lexer::T_GREATER_THAN:
+ 197 $comparisonMethod = 'gt';
+ 198 $expectedTokenType = Lexer::T_OPERAND;
+ 199
+ 200 break;
+ 201
+ 202 case Lexer::T_GREATER_THAN_EQUALS:
+ 203 $comparisonMethod = 'gte';
+ 204 $expectedTokenType = Lexer::T_OPERAND;
+ 205
+ 206 break;
+ 207
+ 208 case Lexer::T_LOWER_THAN:
+ 209 $comparisonMethod = 'lt';
+ 210 $expectedTokenType = Lexer::T_OPERAND;
+ 211
+ 212 break;
+ 213
+ 214 case Lexer::T_LOWER_THAN_EQUALS:
+ 215 $comparisonMethod = 'lte';
+ 216 $expectedTokenType = Lexer::T_OPERAND;
+ 217
+ 218 break;
+ 219
+ 220 case Lexer::T_NOT_OPEN_SQUARE_BRACKET:
+ 221 $comparisonMethod = 'notIn';
+ 222 $comparisonMultipleOperande = [];
+ 223 $expectedTokenType = Lexer::T_OPERAND | Lexer::T_CLOSE_SQUARE_BRACKET;
+ 224
+ 225 break;
+ 226
+ 227 case Lexer::T_OPEN_SQUARE_BRACKET:
+ 228 $comparisonMethod = 'in';
+ 229 $comparisonMultipleOperande = [];
+ 230 $expectedTokenType = Lexer::T_OPERAND | Lexer::T_CLOSE_SQUARE_BRACKET;
+ 231
+ 232 break;
+ 233
+ 234 case Lexer::T_CLOSE_SQUARE_BRACKET:
+ 235 $expression = \call_user_func_array([$this->expressionBuilder, $comparisonMethod], [$comparisonFirstOperande, $comparisonMultipleOperande]);
+ 236 $comparisonMethod = null;
+ 237 $comparisonFirstOperande = null;
+ 238 $comparisonMultipleOperande = false;
+ 239 $expectedTokenType = Lexer::T_COMPOSITE | Lexer::T_CLOSE_PARENTHESIS;
+ 240
+ 241 break;
+ 242
+ 243 case Lexer::T_DOUBLE_OPEN_CURLY_BRACKET:
+ 244 $comparisonMethod = 'contains';
+ 245 $contains = true;
+ 246 $expectedTokenType = Lexer::T_OPERAND | Lexer::T_DOUBLE_CLOSE_CURLY_BRACKET;
+ 247
+ 248 break;
+ 249
+ 250 case Lexer::T_NOT_DOUBLE_OPEN_CURLY_BRACKET:
+ 251 $comparisonMethod = 'notContains';
+ 252 $contains = true;
+ 253 $expectedTokenType = Lexer::T_OPERAND | Lexer::T_DOUBLE_CLOSE_CURLY_BRACKET;
+ 254
+ 255 break;
+ 256
+ 257 case Lexer::T_DOUBLE_CLOSE_CURLY_BRACKET:
+ 258 $expression = \call_user_func_array([$this->expressionBuilder, $comparisonMethod], [$comparisonFirstOperande, $containsValue]);
+ 259 $comparisonMethod = null;
+ 260 $comparisonFirstOperande = null;
+ 261 $contains = false;
+ 262 $expectedTokenType = Lexer::T_COMPOSITE | Lexer::T_CLOSE_PARENTHESIS;
+ 263
+ 264 break;
+ 265
+ 266 case Lexer::T_AND:
+ 267 case Lexer::T_NOT_AND:
+ 268 case Lexer::T_OR:
+ 269 case Lexer::T_NOT_OR:
+ 270 case Lexer::T_XOR:
+ 271 $currentTokenPrecedence = $this->precedence[$currentTokenType];
+ 272 if (null === $compositeOperator || $currentTokenType === $compositeOperator) {
+ 273 $expressions[] = $expression;
+ 274 $expression = null;
+ 275 $compositeOperator = $currentTokenType;
+ 276 $tokenPrecedence = $currentTokenPrecedence;
+ 277 $expectedTokenType = Lexer::T_OPEN_PARENTHESIS | Lexer::T_INPUT_PARAMETER;
+ 278
+ 279 break;
+ 280 }
+ 281
+ 282 if ($currentTokenPrecedence < $tokenPrecedence) {
+ 283 $expressions[] = $expression;
+ 284 $expression = null;
+ 285 $expressions = [$this->buildComposite($compositeOperator, $expressions)];
+ 286 $compositeOperator = $currentTokenType;
+ 287 $tokenPrecedence = $currentTokenPrecedence;
+ 288 $expectedTokenType = Lexer::T_OPEN_PARENTHESIS | Lexer::T_INPUT_PARAMETER;
+ 289
+ 290 break;
+ 291 }
+ 292
+ 293 if ($currentTokenPrecedence > $tokenPrecedence) {
+ 294 $this->lexerIndex = $currentTokenIndex;
+ 295 $this->lexer->resetPosition($currentTokenIndex);
+ 296 $this->lexer->moveNext();
+ 297 $expression = $this->getExpression($expression);
+ 298
+ 299 break;
+ 300 }
+ 301
+ 302 throw new \LogicException(sprintf(
+ 303 'Token precedence error. Current token precedence %s must be different than %s',
+ 304 $currentTokenPrecedence,
+ 305 $tokenPrecedence
+ 306 ));
+ 307
+ 308 default:
+ 309 throw new \LogicException(sprintf(
+ 310 'Token mismatch. Expected token %s given %s',
+ 311 $this->lexer->getLiteral($expectedTokenType),
+ 312 $currentTokenType
+ 313 ));
+ 314 }
+ 315 }
+ 316
+ 317 if (null !== $expression) {
+ 318 $expressions[] = $expression;
+ 319 }
+ 320
+ 321 if (1 === \count($expressions)) {
+ 322 return $expressions[0];
+ 323 }
+ 324
+ 325 return $this->buildComposite($compositeOperator, $expressions);
+ 326 }
+ 327
+ 328 /**
+ 329 * @param mixed $type
+ 330 * @param mixed $expressions
+ 331 *
+ 332 * @return mixed
+ 333 *
+ 334 * @throws UnknownCompositeTypeException
+ 335 */
+ 336 private function buildComposite($type, $expressions)
+ 337 {
+ 338 switch ($type) {
+ 339 case Lexer::T_AND:
+ 340 return $this->expressionBuilder->andX($expressions);
+ 341
+ 342 case Lexer::T_NOT_AND:
+ 343 return $this->expressionBuilder->nandX($expressions);
+ 344
+ 345 case Lexer::T_OR:
+ 346 return $this->expressionBuilder->orX($expressions);
+ 347
+ 348 case Lexer::T_NOT_OR:
+ 349 return $this->expressionBuilder->norX($expressions);
+ 350
+ 351 case Lexer::T_XOR:
+ 352 return $this->expressionBuilder->xorX($expressions);
+ 353
+ 354 default:
+ 355 throw new UnknownCompositeTypeException($type);
+ 356 }
+ 357 }
+ 358
+ 359 /**
+ 360 * @return null|array
+ 361 */
+ 362 private function getNextToken(): mixed
+ 363 {
+ 364 $this->lexer->moveNext();
+ 365
+ 366 return $this->lexer->token;
+ 367 }
+
+
+368 }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Total
+
+
+
+
+
+
+ CRAP
+
+
+
+
+
+
+ QueryStringParser
+
+
+
+
+
+
+ 3
+
+
+
+
+
+
+ correctServerQueryString
+
+
+
+
+
+
+ 2
+
+
+
+
+
+
+ encodeXpression
+
+
+
+
+
+
+ 1
+
+
+
+
+
+
+
+
+ 1 <?php
+ 2
+ 3 declare(strict_types=1);
+ 4
+ 5 namespace Symftony\Xpression;
+ 6
+ 7 class QueryStringParser
+ 8 {
+ 9 public static function correctServerQueryString(): void
+ 10 {
+ 11 if (isset($_SERVER['QUERY_STRING'])) {
+ 12 $_SERVER['QUERY_STRING'] = self::encodeXpression($_SERVER['QUERY_STRING']);
+ 13 parse_str($_SERVER['QUERY_STRING'], $_GET);
+ 14 }
+ 15 }
+ 16
+ 17 /**
+ 18 * @return string
+ 19 */
+ 20 public static function encodeXpression(string $queryString)
+ 21 {
+ 22 return preg_replace_callback(
+ 23 '/(=)\{([^}]*(?:}}[^}]*)*)(?:(?:}(&))|(?:}$))/',
+ 24 static fn ($matches) => $matches[1].urlencode($matches[2]).($matches[3] ?? ''),
+ 25 urldecode($queryString)
+ 26 );
+ 27 }
+
+
+28 } ","
"],col:[2,"
"],tr:[2,"","
"],td:[3,"
"],_default:[0,"",""]};function ye(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?S.merge([e],n):n}function ve(e,t){for(var n=0,r=e.length;n"," ").append(S.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},S.expr.pseudos.animated=function(t){return S.grep(S.timers,function(e){return t===e.elem}).length},S.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=S.css(e,"position"),c=S(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=S.css(e,"top"),u=S.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,S.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},S.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){S.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===S.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===S.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=S(e).offset()).top+=S.css(e,"borderTopWidth",!0),i.left+=S.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-S.css(r,"marginTop",!0),left:t.left-i.left-S.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===S.css(e,"position"))e=e.offsetParent;return e||re})}}),S.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;S.fn[t]=function(e){return B(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),S.each(["top","left"],function(e,n){S.cssHooks[n]=_e(v.pixelPosition,function(e,t){if(t)return t=Be(e,n),Pe.test(t)?S(e).position()[n]+"px":t})}),S.each({Height:"height",Width:"width"},function(a,s){S.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){S.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return B(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?S.css(e,t,i):S.style(e,t,n,i)},s,n?e:void 0,n)}})}),S.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){S.fn[t]=function(e){return this.on(t,e)}}),S.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),S.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){S.fn[n]=function(e,t){return 0
"}),b},a.models.candlestickBarChart=function(){var b=a.models.historicalBarChart(a.models.candlestickBar());return b.useInteractiveGuideline(!0),b.interactiveLayer.tooltip.contentGenerator(function(a){var c=a.series[0].data,d=c.openopen: "+b.yAxis.tickFormat()(c.open)+" close: "+b.yAxis.tickFormat()(c.close)+" high "+b.yAxis.tickFormat()(c.high)+" low: "+b.yAxis.tickFormat()(c.low)+"
"}),b},a.models.legend=function(){"use strict";function b(p){function q(a,b){return"furious"!=o?"#000":m?a.disengaged?"#000":"#fff":m?void 0:(a.color||(a.color=g(a,b)),a.disabled?a.color:"#fff")}function r(a,b){return m&&"furious"==o&&a.disengaged?"#eee":a.color||g(a,b)}function s(a){return m&&"furious"==o?1:a.disabled?0:1}return p.each(function(b){var g=d-c.left-c.right,p=d3.select(this);a.utils.initSVG(p);var t=p.selectAll("g.nv-legend").data([b]),u=t.enter().append("g").attr("class","nvd3 nv-legend").append("g"),v=t.select("g");t.attr("transform","translate("+c.left+","+c.top+")");var w,x,y=v.selectAll(".nv-series").data(function(a){return"furious"!=o?a:a.filter(function(a){return m?!0:!a.disengaged})}),z=y.enter().append("g").attr("class","nv-series");switch(o){case"furious":x=23;break;case"classic":x=20}if("classic"==o)z.append("circle").style("stroke-width",2).attr("class","nv-legend-symbol").attr("r",5),w=y.select("circle");else if("furious"==o){z.append("rect").style("stroke-width",2).attr("class","nv-legend-symbol").attr("rx",3).attr("ry",3),w=y.select(".nv-legend-symbol"),z.append("g").attr("class","nv-check-box").property("innerHTML",'open: "+b.yAxis.tickFormat()(c.open)+" close: "+b.yAxis.tickFormat()(c.close)+" high "+b.yAxis.tickFormat()(c.high)+" low: "+b.yAxis.tickFormat()(c.low)+" s[c]&&(e.offsets.popper[m]+=d[m]+u-s[c]),e.offsets.popper=g(e.offsets.popper);var b=d[m]+d[l]/2-u/2,w=t(e.instance.popper),y=parseFloat(w['margin'+f]),E=parseFloat(w['border'+f+'Width']),v=b-e.offsets.popper[m]-y-E;return v=ee(Q(s[l]-u,v),0),e.arrowElement=i,e.offsets.arrow=(n={},ae(n,m,$(v)),ae(n,h,''),n),e},element:'[x-arrow]'},flip:{order:600,enabled:!0,fn:function(e,t){if(W(e.instance.modifiers,'inner'))return e;if(e.flipped&&e.placement===e.originalPlacement)return e;var o=v(e.instance.popper,e.instance.reference,t.padding,t.boundariesElement,e.positionFixed),n=e.placement.split('-')[0],i=T(n),r=e.placement.split('-')[1]||'',p=[];switch(t.behavior){case ce.FLIP:p=[n,i];break;case ce.CLOCKWISE:p=G(n);break;case ce.COUNTERCLOCKWISE:p=G(n,!0);break;default:p=t.behavior;}return p.forEach(function(s,d){if(n!==s||p.length===d+1)return e;n=e.placement.split('-')[0],i=T(n);var a=e.offsets.popper,l=e.offsets.reference,f=Z,m='left'===n&&f(a.right)>f(l.left)||'right'===n&&f(a.left)