1 | <?php |
||||
2 | |||||
3 | namespace BaoPham\DynamoDb\Parsers; |
||||
4 | |||||
5 | use BaoPham\DynamoDb\ComparisonOperator; |
||||
6 | use BaoPham\DynamoDb\NotSupportedException; |
||||
7 | use BaoPham\DynamoDb\Facades\DynamoDb; |
||||
8 | use Illuminate\Support\Arr; |
||||
9 | |||||
10 | class ConditionExpression |
||||
11 | { |
||||
12 | const OPERATORS = [ |
||||
13 | ComparisonOperator::EQ => '%s = :%s', |
||||
14 | ComparisonOperator::LE => '%s <= :%s', |
||||
15 | ComparisonOperator::LT => '%s < :%s', |
||||
16 | ComparisonOperator::GE => '%s >= :%s', |
||||
17 | ComparisonOperator::GT => '%s > :%s', |
||||
18 | ComparisonOperator::BEGINS_WITH => 'begins_with(%s, :%s)', |
||||
19 | ComparisonOperator::BETWEEN => '(%s BETWEEN :%s AND :%s)', |
||||
20 | ComparisonOperator::CONTAINS => 'contains(%s, :%s)', |
||||
21 | ComparisonOperator::NOT_CONTAINS => 'NOT contains(%s, :%s)', |
||||
22 | ComparisonOperator::NULL => 'attribute_not_exists(%s)', |
||||
23 | ComparisonOperator::NOT_NULL => 'attribute_exists(%s)', |
||||
24 | ComparisonOperator::NE => '%s <> :%s', |
||||
25 | ComparisonOperator::IN => '%s IN (%s)', |
||||
26 | ]; |
||||
27 | |||||
28 | /** |
||||
29 | * @var ExpressionAttributeValues |
||||
30 | */ |
||||
31 | protected $values; |
||||
32 | |||||
33 | /** |
||||
34 | * @var ExpressionAttributeNames |
||||
35 | */ |
||||
36 | protected $names; |
||||
37 | |||||
38 | /** |
||||
39 | * @var Placeholder |
||||
40 | */ |
||||
41 | protected $placeholder; |
||||
42 | |||||
43 | 133 | public function __construct( |
|||
44 | Placeholder $placeholder, |
||||
45 | ExpressionAttributeValues $values, |
||||
46 | ExpressionAttributeNames $names |
||||
47 | ) { |
||||
48 | 133 | $this->placeholder = $placeholder; |
|||
49 | 133 | $this->values = $values; |
|||
50 | 133 | $this->names = $names; |
|||
51 | 133 | } |
|||
52 | |||||
53 | /** |
||||
54 | * @param array $where |
||||
55 | * [ |
||||
56 | * 'column' => 'name', |
||||
57 | * 'type' => 'EQ', |
||||
58 | * 'value' => 'foo', |
||||
59 | * 'boolean' => 'and', |
||||
60 | * ] |
||||
61 | * |
||||
62 | * @return string |
||||
63 | * @throws NotSupportedException |
||||
64 | */ |
||||
65 | 72 | public function parse($where) |
|||
66 | { |
||||
67 | 72 | if (empty($where)) { |
|||
68 | return ''; |
||||
69 | } |
||||
70 | |||||
71 | 72 | $parsed = []; |
|||
72 | |||||
73 | 72 | foreach ($where as $condition) { |
|||
74 | 72 | $boolean = Arr::get($condition, 'boolean'); |
|||
75 | 72 | $value = Arr::get($condition, 'value'); |
|||
76 | 72 | $type = Arr::get($condition, 'type'); |
|||
77 | |||||
78 | 72 | $prefix = ''; |
|||
79 | |||||
80 | 72 | if (count($parsed) > 0) { |
|||
81 | 45 | $prefix = strtoupper($boolean) . ' '; |
|||
0 ignored issues
–
show
Bug
introduced
by
![]() |
|||||
82 | } |
||||
83 | |||||
84 | 72 | if ($type === 'Nested') { |
|||
85 | 3 | $parsed[] = $prefix . $this->parseNestedCondition($value); |
|||
0 ignored issues
–
show
It seems like
$value can also be of type null ; however, parameter $conditions of BaoPham\DynamoDb\Parsers...:parseNestedCondition() does only seem to accept array , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
86 | 3 | continue; |
|||
87 | } |
||||
88 | |||||
89 | 72 | $parsed[] = $prefix . $this->parseCondition( |
|||
90 | 72 | Arr::get($condition, 'column'), |
|||
91 | 72 | $type, |
|||
92 | 72 | $value |
|||
93 | ); |
||||
94 | } |
||||
95 | |||||
96 | 72 | return implode(' ', $parsed); |
|||
97 | } |
||||
98 | |||||
99 | 124 | public function reset() |
|||
100 | { |
||||
101 | 124 | $this->placeholder->reset(); |
|||
102 | 124 | $this->names->reset(); |
|||
103 | 124 | $this->values->reset(); |
|||
104 | 124 | } |
|||
105 | |||||
106 | 62 | protected function getSupportedOperators() |
|||
107 | { |
||||
108 | 62 | return static::OPERATORS; |
|||
109 | } |
||||
110 | |||||
111 | 3 | protected function parseNestedCondition(array $conditions) |
|||
112 | { |
||||
113 | 3 | return '(' . $this->parse($conditions) . ')'; |
|||
114 | } |
||||
115 | |||||
116 | 72 | protected function parseCondition($name, $operator, $value) |
|||
117 | { |
||||
118 | 72 | $operators = $this->getSupportedOperators(); |
|||
119 | |||||
120 | 72 | if (empty($operators[$operator])) { |
|||
121 | throw new NotSupportedException("$operator is not supported"); |
||||
122 | } |
||||
123 | |||||
124 | 72 | $template = $operators[$operator]; |
|||
125 | |||||
126 | 72 | $this->names->set($name); |
|||
127 | |||||
128 | 72 | if ($operator === ComparisonOperator::BETWEEN) { |
|||
129 | 3 | return $this->parseBetweenCondition($name, $value, $template); |
|||
130 | } |
||||
131 | |||||
132 | 70 | if ($operator === ComparisonOperator::IN) { |
|||
133 | 3 | return $this->parseInCondition($name, $value, $template); |
|||
134 | } |
||||
135 | |||||
136 | 68 | if ($operator === ComparisonOperator::NULL || $operator === ComparisonOperator::NOT_NULL) { |
|||
137 | 5 | return $this->parseNullCondition($name, $template); |
|||
138 | } |
||||
139 | |||||
140 | 64 | $placeholder = $this->placeholder->next(); |
|||
141 | |||||
142 | 64 | $this->values->set($placeholder, DynamoDb::marshalValue($value)); |
|||
143 | |||||
144 | 64 | return sprintf($template, $this->names->placeholder($name), $placeholder); |
|||
145 | } |
||||
146 | |||||
147 | 3 | protected function parseBetweenCondition($name, $value, $template) |
|||
148 | { |
||||
149 | 3 | $first = $this->placeholder->next(); |
|||
150 | |||||
151 | 3 | $second = $this->placeholder->next(); |
|||
152 | |||||
153 | 3 | $this->values->set($first, DynamoDb::marshalValue($value[0])); |
|||
154 | |||||
155 | 3 | $this->values->set($second, DynamoDb::marshalValue($value[1])); |
|||
156 | |||||
157 | 3 | return sprintf($template, $this->names->placeholder($name), $first, $second); |
|||
158 | } |
||||
159 | |||||
160 | 3 | protected function parseInCondition($name, $value, $template) |
|||
161 | { |
||||
162 | 3 | $valuePlaceholders = []; |
|||
163 | |||||
164 | 3 | foreach ($value as $item) { |
|||
165 | 3 | $placeholder = $this->placeholder->next(); |
|||
166 | |||||
167 | 3 | $valuePlaceholders[] = ":" . $placeholder; |
|||
168 | |||||
169 | 3 | $this->values->set($placeholder, DynamoDb::marshalValue($item)); |
|||
170 | } |
||||
171 | |||||
172 | 3 | return sprintf($template, $this->names->placeholder($name), implode(', ', $valuePlaceholders)); |
|||
173 | } |
||||
174 | |||||
175 | 5 | protected function parseNullCondition($name, $template) |
|||
176 | { |
||||
177 | 5 | return sprintf($template, $this->names->placeholder($name)); |
|||
178 | } |
||||
179 | } |
||||
180 |