CompilesDataManipulations::createUpdateObject()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 14
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 7
c 1
b 0
f 0
nc 3
nop 1
dl 0
loc 14
ccs 0
cts 8
cp 0
crap 12
rs 10
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 80
    public function compileInsert(Builder|IlluminateQueryBuilder $query, array $values, ?string $bindVar = null)
20
    {
21 80
        $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 80
        if (empty($values)) {
24
            $aql = /** @lang AQL */ 'INSERT {} INTO ' . $table . ' RETURN NEW._key';
25
26
            return $aql;
27
        }
28
29 80
        return /** @lang AQL */ 'LET values = ' . $bindVar
30 80
            . ' FOR value IN values'
31 80
            . ' INSERT value INTO ' . $table
32 80
            . ' 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 32
    public function compileInsertGetId(IlluminateQueryBuilder $query, $values, $sequence = '_key', ?string $bindVar = null)
45
    {
46 32
        $table = $this->prefixTable($query->from);
47
48 32
        $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 32
        if (empty($values)) {
51
            $aql = /** @lang AQL */ 'INSERT {} INTO ' . $table . ' RETURN NEW.' . $sequence;
52
53
            return $aql;
54
        }
55
56 32
        $aql = /** @lang AQL */ 'LET values = ' . $bindVar
57 32
            . ' FOR value IN values'
58 32
            . ' INSERT value INTO ' . $table
59 32
            . ' RETURN NEW.' . $sequence;
60
61 32
        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 64
    public function compileInsertOrIgnore(IlluminateQueryBuilder $query, array $values, ?string $bindVar = null)
72
    {
73 64
        $table = $this->prefixTable($query->from);
74
75 64
        if (empty($values)) {
76
            $aql = /** @lang AQL */ "INSERT {} INTO $table RETURN NEW._key";
77
78
            return $aql;
79
        }
80
81 64
        $aql = /** @lang AQL */ "LET values = $bindVar "
82 64
            . "FOR value IN values "
83 64
            . "INSERT value INTO $table "
84 64
            . "OPTIONS { ignoreErrors: true } "
85 64
            . "RETURN NEW._key";
86
87 64
        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 2
    public function compileInsertUsing(IlluminateQueryBuilder $query, array $columns, string $sql)
99
    {
100 2
        $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 2
        $insertDoc = '';
103 2
        if (empty($columns) || $columns === ['*']) {
104
            $insertDoc = 'docDoc';
105
        }
106
107
108 2
        if ($insertDoc === '') {
109 2
            $insertValues = [];
110 2
            foreach ($columns as $column) {
111 2
                $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 2
            $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 2
        $aql = /** @lang AQL */ 'LET docs = ' . $sql
117 2
            . ' FOR docDoc IN docs'
118 2
            . ' INSERT ' . $insertDoc . ' INTO ' . $table
119 2
            . ' RETURN NEW._key';
120
121
122 2
        return $aql;
123
    }
124
125
    /**
126
     * Compile an insert statement using a subquery into SQL.
127
     *
128
     * @param  IlluminateQueryBuilder  $query
129
     * @param  array<mixed>  $columns
130
     * @param  string  $sql
131
     * @return string
132
     */
133 2
    public function compileInsertOrIgnoreUsing(IlluminateQueryBuilder $query, array $columns, string $sql)
134
    {
135 2
        $table = $this->wrapTable($query->from);
136
137 2
        $insertDoc = '';
138 2
        if (empty($columns) || $columns === ['*']) {
139
            $insertDoc = 'docDoc';
140
        }
141
142
143 2
        if ($insertDoc === '') {
144 2
            $insertValues = [];
145 2
            foreach ($columns as $column) {
146 2
                $insertValues[$column] = $this->normalizeColumnReferences($query, $column, 'docs');
147
            }
148 2
            $insertDoc = $this->generateAqlObject($insertValues);
149
        }
150
151 2
        $aql = /** @lang AQL */ 'LET docs = ' . $sql
152 2
            . ' FOR docDoc IN docs'
153 2
            . ' INSERT ' . $insertDoc . ' INTO ' . $table
154 2
            . ' OPTIONS { ignoreErrors: true }'
155 2
            . ' RETURN NEW._key';
156
157 2
        return $aql;
158
    }
159
160
    /**
161
     * @param array<mixed> $values
162
     * @return string
163
     */
164
    protected function createUpdateObject($values)
165
    {
166
        $valueStrings = [];
167
        foreach ($values as $key => $value) {
168
            if (is_array($value)) {
169
                $valueStrings[] = $key . ': ' . $this->createUpdateObject($value);
170
171
                continue;
172
            }
173
174
            $valueStrings[] = $key . ': ' . $value;
175
        }
176
177
        return '{ ' . implode(', ', $valueStrings) . ' }';
178
    }
179
180
    /**
181
     * Compile an update statement into AQL.
182
     *
183
     * @param  \Illuminate\Database\Query\Builder  $query
184
     * @param  array<mixed>  $values
185
     * @return string
186
     */
187 26
    public function compileUpdate(IlluminateQueryBuilder $query, array|string $values)
188
    {
189
        assert($query instanceof Builder);
190
191 26
        $table = $this->getValue($query->from);
0 ignored issues
show
Bug introduced by
It seems like getValue() 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

191
        /** @scrutinizer ignore-call */ 
192
        $table = $this->getValue($query->from);
Loading history...
192 26
        $alias = $query->getTableAlias($query->from);
193
194 26
        if (!is_array($values)) {
0 ignored issues
show
introduced by
The condition is_array($values) is always true.
Loading history...
195
            $values = Arr::wrap($values);
196
        }
197
198 26
        $updateValues = $this->generateAqlObject($values);
199
200 26
        $aqlElements = [];
201 26
        $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

201
        /** @scrutinizer ignore-call */ 
202
        $aqlElements[] = $this->compileFrom($query, $query->from);
Loading history...
202
203 26
        if (!empty($query->joins)) {
204 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

204
            /** @scrutinizer ignore-call */ 
205
            $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...
205
        }
206
207 26
        $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

207
        /** @scrutinizer ignore-call */ 
208
        $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...
208
209 26
        $aqlElements[] = 'UPDATE ' . $alias . ' WITH ' . $updateValues . ' IN ' . $table;
210
211 26
        return implode(' ', $aqlElements);
212
    }
213
214
    /**
215
     * Compile an "upsert" statement into AQL.
216
     *
217
     * @param  \Illuminate\Database\Query\Builder  $query
218
     * @param  array<mixed>  $values
219
     * @param  array<mixed>  $uniqueBy
220
     * @param  array<mixed>  $update
221
     * @return string
222
     */
223 6
    public function compileUpsert(IlluminateQueryBuilder $query, array $values, array $uniqueBy, array $update)
224
    {
225 6
        $searchFields = [];
226 6
        foreach ($uniqueBy as $field) {
227 6
            $searchFields[$field] = 'doc.' . $field;
228
        }
229 6
        $searchObject = $this->generateAqlObject($searchFields);
230
231 6
        $updateFields = [];
232 6
        foreach ($update as $field) {
233 6
            $updateFields[$field] = 'doc.' . $field;
234
        }
235 6
        $updateObject = $this->generateAqlObject($updateFields);
236
237 6
        $valueObjects = [];
238 6
        foreach ($values as $data) {
239 6
            $valueObjects[] = $this->generateAqlObject($data);
240
        }
241
242 6
        return 'LET docs = [' . implode(', ', $valueObjects) . ']'
243 6
            . ' FOR doc IN docs'
244 6
            . ' UPSERT ' . $searchObject
245 6
            . ' INSERT doc'
246 6
            . ' UPDATE ' . $updateObject
247 6
            . ' IN ' . $this->getValue($query->from);
248
    }
249
250
    /**
251
     * Compile a delete statement into SQL.
252
     *
253
     * @param  \Illuminate\Database\Query\Builder  $query
254
     * @return string
255
     */
256 38
    public function compileDelete(IlluminateQueryBuilder $query)
257
    {
258 38
        $table = (string) $this->getValue($query->from);
259
260 38
        $where = $this->compileWheres($query);
261
262 38
        return trim(
263 38
            !empty($query->joins)
264
                ? $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

264
                ? $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...
265 38
                : $this->compileDeleteWithoutJoins($query, $table, $where),
266 38
        );
267
    }
268
269
    /**
270
     * Compile a delete statement without joins into SQL.
271
     *
272
     * @param  \Illuminate\Database\Query\Builder  $query
273
     * @param  string  $table
274
     * @param  string  $where
275
     * @return string
276
     */
277 38
    protected function compileDeleteWithoutJoins(IlluminateQueryBuilder $query, $table, $where)
278
    {
279
        assert($query instanceof Builder);
280
281 38
        $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

281
        /** @scrutinizer ignore-call */ 
282
        $alias = $this->normalizeColumn($query, $query->registerTableAlias($table));
Loading history...
282
283 38
        $table = $this->wrapTable($this->prefixTable($table));
284
285 38
        return "FOR {$alias} IN {$table} {$where} REMOVE {$alias} IN {$table}";
286
    }
287
288
    /**
289
     * Compile a truncate table statement into SQL.
290
     *
291
     * @param  IlluminateQueryBuilder  $query
292
     * @return array<mixed>
293
     */
294 3
    public function compileTruncate(IlluminateQueryBuilder $query)
295
    {
296 3
        return [$this->compileDelete($query) => []];
297
    }
298
299
}
300