Completed
Pull Request — master (#212)
by Alexandru
45:00 queued 03:00
created

ConditionExpression::parseCondition()   A

Complexity

Conditions 6
Paths 5

Size

Total Lines 29
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 14
CRAP Score 6.0106

Importance

Changes 0
Metric Value
eloc 14
dl 0
loc 29
ccs 14
cts 15
cp 0.9333
rs 9.2222
c 0
b 0
f 0
cc 6
nc 5
nop 3
crap 6.0106
1
<?php
2
3
namespace Rennokki\DynamoDb\Parsers;
4
5
use Illuminate\Support\Arr;
6
use Rennokki\DynamoDb\ComparisonOperator;
7
use Rennokki\DynamoDb\NotSupportedException;
8
use Rennokki\DynamoDb\Facades\DynamoDb;
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 13
    public function __construct(
44
        Placeholder $placeholder,
45
        ExpressionAttributeValues $values,
46
        ExpressionAttributeNames $names
47
    ) {
48 13
        $this->placeholder = $placeholder;
49 13
        $this->values = $values;
50 13
        $this->names = $names;
51 13
    }
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 5
    public function parse($where)
66
    {
67 5
        if (empty($where)) {
68
            return '';
69
        }
70
71 5
        $parsed = [];
72
73 5
        foreach ($where as $condition) {
74 5
            $boolean = Arr::get($condition, 'boolean');
75 5
            $value = Arr::get($condition, 'value');
76 5
            $type = Arr::get($condition, 'type');
77
78 5
            $prefix = '';
79
80 5
            if (count($parsed) > 0) {
81 3
                $prefix = strtoupper($boolean) . ' ';
82
            }
83
84 5
            if ($type === 'Nested') {
85 1
                $parsed[] = $prefix . $this->parseNestedCondition($value);
0 ignored issues
show
Bug introduced by
It seems like $value can also be of type null; however, parameter $conditions of Rennokki\DynamoDb\Parser...: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 ignore-type  annotation

85
                $parsed[] = $prefix . $this->parseNestedCondition(/** @scrutinizer ignore-type */ $value);
Loading history...
86 1
                continue;
87
            }
88
89 5
            $parsed[] = $prefix . $this->parseCondition(
90 5
                Arr::get($condition, 'column'),
91 5
                $type,
92 5
                $value
93
            );
94
        }
95
96 5
        return implode(' ', $parsed);
97
    }
98
99 9
    public function reset()
100
    {
101 9
        $this->placeholder->reset();
102 9
        $this->names->reset();
103 9
        $this->values->reset();
104 9
    }
105
106 4
    protected function getSupportedOperators()
107
    {
108 4
        return static::OPERATORS;
109
    }
110
111 1
    protected function parseNestedCondition(array $conditions)
112
    {
113 1
        return '(' . $this->parse($conditions) . ')';
114
    }
115
116 5
    protected function parseCondition($name, $operator, $value)
117
    {
118 5
        $operators = $this->getSupportedOperators();
119
120 5
        if (empty($operators[$operator])) {
121
            throw new NotSupportedException("$operator is not supported");
122
        }
123
124 5
        $template = $operators[$operator];
125
126 5
        $this->names->set($name);
127
128 5
        if ($operator === ComparisonOperator::BETWEEN) {
129 1
            return $this->parseBetweenCondition($name, $value, $template);
130
        }
131
132 5
        if ($operator === ComparisonOperator::IN) {
133 1
            return $this->parseInCondition($name, $value, $template);
134
        }
135
136 5
        if ($operator === ComparisonOperator::NULL || $operator === ComparisonOperator::NOT_NULL) {
137 1
            return $this->parseNullCondition($name, $template);
138
        }
139
140 5
        $placeholder = $this->placeholder->next();
141
142 5
        $this->values->set($placeholder, DynamoDb::marshalValue($value));
143
144 5
        return sprintf($template, $this->names->placeholder($name), $placeholder);
145
    }
146
147 1
    protected function parseBetweenCondition($name, $value, $template)
148
    {
149 1
        $first = $this->placeholder->next();
150
151 1
        $second = $this->placeholder->next();
152
153 1
        $this->values->set($first, DynamoDb::marshalValue($value[0]));
154
155 1
        $this->values->set($second, DynamoDb::marshalValue($value[1]));
156
157 1
        return sprintf($template, $this->names->placeholder($name), $first, $second);
158
    }
159
160 1
    protected function parseInCondition($name, $value, $template)
161
    {
162 1
        $valuePlaceholders = [];
163
164 1
        foreach ($value as $item) {
165 1
            $placeholder = $this->placeholder->next();
166
167 1
            $valuePlaceholders[] = ":" . $placeholder;
168
169 1
            $this->values->set($placeholder, DynamoDb::marshalValue($item));
170
        }
171
172 1
        return sprintf($template, $this->names->placeholder($name), implode(', ', $valuePlaceholders));
173
    }
174
175 1
    protected function parseNullCondition($name, $template)
176
    {
177 1
        return sprintf($template, $this->names->placeholder($name));
178
    }
179
}
180