Passed
Push — next ( d224bd...9e651f )
by Bas
15:29 queued 11:57
created

CompilesDataManipulations::compileUpdate()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 25
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 3.004

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 13
c 1
b 0
f 0
nc 4
nop 2
dl 0
loc 25
ccs 12
cts 13
cp 0.9231
crap 3.004
rs 9.8333
1
<?php
2
3
namespace LaravelFreelancerNL\Aranguent\Query\Concerns;
4
5
use Illuminate\Database\Query\Builder as IlluminateQueryBuilder;
6
use Illuminate\Support\Arr;
7
use LaravelFreelancerNL\Aranguent\Query\Builder;
8
9
trait CompilesDataManipulations
10
{
11
    /**
12
     * Compile an insert statement into AQL.
13
     *
14
     * @param Builder|IlluminateQueryBuilder $query
15
     * @param array<mixed> $values
16
     * @param string|null $bindVar
17
     * @return string
18
     */
19 23
    public function compileInsert(Builder|IlluminateQueryBuilder $query, array $values, string $bindVar = null)
20
    {
21 23
        $table = $this->prefixTable($query->from);
0 ignored issues
show
Bug introduced by
It seems like prefixTable() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

21
        /** @scrutinizer ignore-call */ 
22
        $table = $this->prefixTable($query->from);
Loading history...
22
23 23
        if (empty($values)) {
24
            $aql = /** @lang AQL */ 'INSERT {} INTO ' . $table . ' RETURN NEW._key';
25
26
            return $aql;
27
        }
28
29 23
        return /** @lang AQL */ 'LET values = ' . $bindVar
30 23
            . ' FOR value IN values'
31 23
            . ' INSERT value INTO ' . $table
32 23
            . ' RETURN NEW._key';
33
    }
34
35
    /**
36
     * Compile an insert and get ID statement into SQL.
37
     *
38
     * @param IlluminateQueryBuilder $query
39
     * @param array<mixed> $values
40
     * @param null|string $sequence
41
     * @param string|null $bindVar
42
     * @return string
43
     */
44 13
    public function compileInsertGetId(IlluminateQueryBuilder $query, $values, $sequence = '_key', string $bindVar = null)
45
    {
46 13
        $table = $this->prefixTable($query->from);
47
48 13
        $sequence = $this->convertIdToKey($sequence);
0 ignored issues
show
Bug introduced by
It seems like convertIdToKey() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

48
        /** @scrutinizer ignore-call */ 
49
        $sequence = $this->convertIdToKey($sequence);
Loading history...
49
50 13
        if (empty($values)) {
51
            $aql = /** @lang AQL */ 'INSERT {} INTO ' . $table . ' RETURN NEW.' . $sequence;
52
53
            return $aql;
54
        }
55
56 13
        $aql = /** @lang AQL */ 'LET values = ' . $bindVar
57 13
            . ' FOR value IN values'
58 13
            . ' INSERT value INTO ' . $table
59 13
            . ' RETURN NEW.' . $sequence;
60
61 13
        return $aql;
62
    }
63
64
    /**
65
     * Compile an insert statement into AQL.
66
     *
67
     * @param IlluminateQueryBuilder $query
68
     * @param array<mixed> $values
69
     * @return string
70
     */
71 5
    public function compileInsertOrIgnore(IlluminateQueryBuilder $query, array $values, string $bindVar = null)
72
    {
73 5
        $table = $this->prefixTable($query->from);
74
75 5
        if (empty($values)) {
76
            $aql = /** @lang AQL */ "INSERT {} INTO $table RETURN NEW._key";
77
78
            return $aql;
79
        }
80
81 5
        $aql = /** @lang AQL */ "LET values = $bindVar "
82 5
            . "FOR value IN values "
83 5
            . "INSERT value INTO $table "
84 5
            . "OPTIONS { ignoreErrors: true } "
85 5
            . "RETURN NEW._key";
86
87 5
        return $aql;
88
    }
89
90
    /**
91
     * Compile an insert statement using a subquery into SQL.
92
     *
93
     * @param  IlluminateQueryBuilder  $query
94
     * @param  array<mixed>  $columns
95
     * @param  string  $sql
96
     * @return string
97
     */
98 1
    public function compileInsertUsing(IlluminateQueryBuilder $query, array $columns, string $sql)
99
    {
100 1
        $table = $this->wrapTable($query->from);
0 ignored issues
show
Bug introduced by
It seems like wrapTable() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

100
        /** @scrutinizer ignore-call */ 
101
        $table = $this->wrapTable($query->from);
Loading history...
101
102 1
        $insertDoc = '';
103 1
        if (empty($columns) || $columns === ['*']) {
104
            $insertDoc = 'docDoc';
105
        }
106
107
108 1
        if ($insertDoc === '') {
109 1
            $insertValues = [];
110 1
            foreach($columns as $column) {
111 1
                $insertValues[$column] = $this->normalizeColumnReferences($query, $column, 'docs');
0 ignored issues
show
Bug introduced by
It seems like normalizeColumnReferences() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

111
                /** @scrutinizer ignore-call */ 
112
                $insertValues[$column] = $this->normalizeColumnReferences($query, $column, 'docs');
Loading history...
112
            }
113 1
            $insertDoc = $this->generateAqlObject($insertValues);
0 ignored issues
show
Bug introduced by
It seems like generateAqlObject() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

113
            /** @scrutinizer ignore-call */ 
114
            $insertDoc = $this->generateAqlObject($insertValues);
Loading history...
114
        }
115
116 1
        $aql = /** @lang AQL */ 'LET docs = ' . $sql
117 1
            . ' FOR docDoc IN docs'
118 1
            . ' INSERT ' . $insertDoc . ' INTO ' . $table
119 1
            . ' RETURN NEW._key';
120
121
122 1
        return $aql;
123
    }
124
125
    /**
126
     * @param array<mixed> $values
127
     * @return string
128
     */
129
    protected function createUpdateObject($values)
130
    {
131
        $valueStrings = [];
132
        foreach($values as $key => $value) {
133
            if (is_array($value)) {
134
                $valueStrings[] = $key . ': ' . $this->createUpdateObject($value);
135
136
                continue;
137
            }
138
139
            $valueStrings[] = $key . ': ' . $value;
140
        }
141
142
        return '{ ' . implode(', ', $valueStrings) . ' }';
143
    }
144
145
    /**
146
     * Compile an update statement into AQL.
147
     *
148
     * @param  \Illuminate\Database\Query\Builder  $query
149
     * @param  array<mixed>  $values
150
     * @return string
151
     */
152 31
    public function compileUpdate(IlluminateQueryBuilder $query, array|string $values)
153
    {
154
        assert($query instanceof Builder);
155
156 31
        $table = $query->from;
157 31
        $alias = $query->getTableAlias($query->from);
158
159 31
        if (!is_array($values)) {
0 ignored issues
show
introduced by
The condition is_array($values) is always true.
Loading history...
160
            $values = Arr::wrap($values);
161
        }
162
163 31
        $updateValues = $this->generateAqlObject($values);
164
165 31
        $aqlElements = [];
166 31
        $aqlElements[] = $this->compileFrom($query, $query->from);
0 ignored issues
show
Bug introduced by
It seems like compileFrom() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

166
        /** @scrutinizer ignore-call */ 
167
        $aqlElements[] = $this->compileFrom($query, $query->from);
Loading history...
167
168 31
        if (!empty($query->joins)) {
169 1
            $aqlElements[] = $this->compileJoins($query, $query->joins);
0 ignored issues
show
Bug introduced by
The method compileJoins() does not exist on LaravelFreelancerNL\Aran...mpilesDataManipulations. Did you maybe mean compileInsert()? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

169
            /** @scrutinizer ignore-call */ 
170
            $aqlElements[] = $this->compileJoins($query, $query->joins);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
170
        }
171
172 31
        $aqlElements[] = $this->compileWheres($query);
0 ignored issues
show
Bug introduced by
The method compileWheres() does not exist on LaravelFreelancerNL\Aran...mpilesDataManipulations. Did you maybe mean compileInsert()? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

172
        /** @scrutinizer ignore-call */ 
173
        $aqlElements[] = $this->compileWheres($query);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
173
174 31
        $aqlElements[] = 'UPDATE ' . $alias . ' WITH ' . $updateValues . ' IN ' . $table;
175
176 31
        return implode(' ', $aqlElements);
177
    }
178
179
    /**
180
     * Compile an "upsert" statement into AQL.
181
     *
182
     * @param  \Illuminate\Database\Query\Builder  $query
183
     * @param  array<mixed>  $values
184
     * @param  array<mixed>  $uniqueBy
185
     * @param  array<mixed>  $update
186
     * @return string
187
     */
188 5
    public function compileUpsert(IlluminateQueryBuilder $query, array $values, array $uniqueBy, array $update)
189
    {
190 5
        $searchFields = [];
191 5
        foreach($uniqueBy as $field) {
192 5
            $searchFields[$field] = 'doc.' . $field;
193
        }
194 5
        $searchObject = $this->generateAqlObject($searchFields);
195
196 5
        $updateFields = [];
197 5
        foreach($update as $field) {
198 5
            $updateFields[$field] = 'doc.' . $field;
199
        }
200 5
        $updateObject = $this->generateAqlObject($updateFields);
201
202 5
        $valueObjects = [];
203 5
        foreach($values as $data) {
204 5
            $valueObjects[] = $this->generateAqlObject($data);
205
        }
206
207 5
        return 'LET docs = [' . implode(', ', $valueObjects) . ']'
208 5
            . ' FOR doc IN docs'
209 5
            . ' UPSERT ' . $searchObject
210 5
            . ' INSERT doc'
211 5
            . ' UPDATE ' . $updateObject
212 5
            . ' IN ' . $query->from;
213
    }
214
215
    /**
216
     * Compile a delete statement into SQL.
217
     *
218
     * @param  \Illuminate\Database\Query\Builder  $query
219
     * @return string
220
     */
221 23
    public function compileDelete(IlluminateQueryBuilder $query)
222
    {
223 23
        $table = $query->from;
224
225 23
        $where = $this->compileWheres($query);
226
227 23
        return trim(
228 23
            !empty($query->joins)
229
                ? $this->compileDeleteWithJoins($query, $table, $where)
0 ignored issues
show
Bug introduced by
The method compileDeleteWithJoins() does not exist on LaravelFreelancerNL\Aran...mpilesDataManipulations. Did you maybe mean compileDelete()? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

229
                ? $this->/** @scrutinizer ignore-call */ compileDeleteWithJoins($query, $table, $where)

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
230 23
                : $this->compileDeleteWithoutJoins($query, $table, $where)
231 23
        );
232
    }
233
234
    /**
235
     * Compile a delete statement without joins into SQL.
236
     *
237
     * @param  \Illuminate\Database\Query\Builder  $query
238
     * @param  string  $table
239
     * @param  string  $where
240
     * @return string
241
     */
242 23
    protected function compileDeleteWithoutJoins(IlluminateQueryBuilder $query, $table, $where)
243
    {
244
        assert($query instanceof Builder);
245
246 23
        $alias = $this->normalizeColumn($query, $query->registerTableAlias($table));
0 ignored issues
show
Bug introduced by
It seems like normalizeColumn() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

246
        /** @scrutinizer ignore-call */ 
247
        $alias = $this->normalizeColumn($query, $query->registerTableAlias($table));
Loading history...
247
248 23
        $table = $this->wrapTable($this->prefixTable($table));
249
250 23
        return "FOR {$alias} IN {$table} {$where} REMOVE {$alias} IN {$table}";
251
    }
252
253
    /**
254
     * Compile a truncate table statement into SQL.
255
     *
256
     * @param  IlluminateQueryBuilder  $query
257
     * @return array<mixed>
258
     */
259 2
    public function compileTruncate(IlluminateQueryBuilder $query)
260
    {
261 2
        return [$this->compileDelete($query) => []];
262
    }
263
264
}
265