baopham /
laravel-dynamodb
| 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
Loading history...
|
|||||
| 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
Loading history...
|
|||||
| 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 |