Completed
Push — master ( 87170e...c34495 )
by Darío
02:39
created

TableGateway   F

Complexity

Total Complexity 66

Size/Duplication

Total Lines 431
Duplicated Lines 0 %

Test Coverage

Coverage 56.99%

Importance

Changes 0
Metric Value
eloc 207
dl 0
loc 431
ccs 110
cts 193
cp 0.5699
rs 3.12
c 0
b 0
f 0
wmc 66

6 Methods

Rating   Name   Duplication   Size   Complexity  
A getLastQuery() 0 3 1
C select() 0 79 14
B insert() 0 65 11
C delete() 0 74 13
D update() 0 132 26
A getLastValues() 0 3 1

How to fix   Complexity   

Complex Class

Complex classes like TableGateway often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use TableGateway, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * DronePHP (http://www.dronephp.com)
4
 *
5
 * @link      http://github.com/Pleets/DronePHP
6
 * @copyright Copyright (c) 2016-2018 Pleets. (http://www.pleets.org)
7
 * @license   http://www.dronephp.com/license
8
 * @author    Darío Rivera <[email protected]>
9
 */
10
11
namespace Drone\Db\TableGateway;
12
13
use Drone\Db\SQLFunction;
14
use Drone\Exception;
15
16
/**
17
 * TableGateway class
18
 *
19
 * This class is a query builder for CRUD (create, read, update, delete)
20
 */
21
class TableGateway extends AbstractTableGateway implements TableGatewayInterface
22
{
23
    /**
24
     * The text with the last query executed
25
     *
26
     * @var string
27
     */
28
    protected $lastQuery;
29
30
    /**
31
     * An array with the last binded values
32
     *
33
     * @var array
34
     */
35
    protected $lastValues;
36
37
    /**
38
     * Returns the lastQuery
39
     *
40
     * @return string
41
     */
42
    public function getLastQuery()
43
    {
44
        return $this->lastQuery;
45
    }
46
47
    /**
48
     * Returns the lastValues
49
     *
50
     * @return array
51
     */
52
    public function getLastValues()
53
    {
54
        return $this->lastValues;
55
    }
56
57
    /**
58
     * Select statement
59
     *
60
     * @param array $where
61
     *
62
     * @return array With all results
63
     */
64 2
    public function select(Array $where = [])
0 ignored issues
show
Coding Style introduced by
As per coding-style, PHP keywords should be in lowercase; expected array, but found Array.
Loading history...
65
    {
66 2
        $bind_values = [];
67
68 2
        $driver = $this->getDb()->getDriverName();
69
70 2
        if (count($where))
71
        {
72 2
            $parsed_where = [];
73
74 2
            $k = 0;
75
76 2
            foreach ($where as $key => $value)
77
            {
78 2
                $k++;
79
80 2
                if (is_null($value))
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
81
                    $parsed_where[] = "$key IS NULL";
82 2
                elseif ($value instanceof SQLFunction)
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
83
                    $parsed_where[] = "$key = " . $value->getStatement();
84 2
                elseif (is_array($value))
85
                {
86
                    $parsed_in = [];
87
88
                    foreach ($value as $in_value)
89
                    {
90
                        switch ($driver)
91
                        {
92
                            case 'Oci8':
93
                                $parsed_in[] = ":$k";
94
                                $bind_values[":$k"] = $in_value;
95
                                break;
96
97
                            case 'Mysqli' || 'Sqlsrv':
98
                                $parsed_in[] = "?";
99
                                $bind_values[] = $in_value;
100
                                break;
101
                        }
102
103
                        $k++;
104
                    }
105
106
                    $parsed_where[] = "$key IN (" . implode(", ", $parsed_in) . ")";
107
                }
108
                else
0 ignored issues
show
Coding Style introduced by
Expected 1 space after ELSE keyword; newline found
Loading history...
109
                {
110
                    switch ($driver)
111
                    {
112 2
                        case 'Oci8':
113
                            $parsed_where[] = "$key = :$k";
114
                            $bind_values[":$k"] = $value;
115
                            break;
116
117 2
                        case 'Mysqli' || 'Sqlsrv':
118 2
                            $parsed_where[] = "$key = ?";
119 2
                            $bind_values[] = $value;
120 2
                            break;
121
                    }
122
                }
123
            }
124
125 2
            $where = "WHERE \r\n\t" . implode(" AND\r\n\t", $parsed_where);
126
        }
127
        else
0 ignored issues
show
Coding Style introduced by
Expected 1 space after ELSE keyword; newline found
Loading history...
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
128
            $where = "";
129
130 2
        $table = $this->entity->getTableName();
131
132 2
        $sql = "SELECT * \r\nFROM {$table}\r\n$where";
133
134 2
        $this->lastQuery = $sql;
135 2
        $this->lastValues = $bind_values;
136
137 2
        if (count($bind_values))
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
138 2
            $this->getDb()->execute($sql, $bind_values);
139
        else
0 ignored issues
show
Coding Style introduced by
Expected 1 space after ELSE keyword; newline found
Loading history...
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
140
            $this->getDb()->execute($sql);
141
142 2
        return $this->getDb()->getArrayResult();
143
    }
144
145
    /**
146
     * Insert statement
147
     *
148
     * @param array $data
149
     *
150
     * @throws RuntimeException from internal execute()
151
     * @throws LogicException
152
     *
153
     * @return resource|object
154
     */
155 3
    public function insert(Array $data)
0 ignored issues
show
Coding Style introduced by
As per coding-style, PHP keywords should be in lowercase; expected array, but found Array.
Loading history...
156
    {
157 3
        if (!count($data))
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
158 1
            throw new \LogicException("Missing values for INSERT statement!");
159
160 2
        $bind_values = [];
161
162 2
        $driver = $this->getDb()->getDriverName();
163
164 2
        $k = 0;
165
166 2
        $null_keys = [];
167
168 2
        foreach ($data as $key => $value)
169
        {
170 2
            $k++;
171
172
            # insert NULL values cause problems when BEFORE INSERT triggers are
173
            # defined to assigns values over fields. For SQLServer is better not
174
            # pass NULL values
175 2
            if ($driver == 'Sqlsrv' && is_null($value))
176
            {
177
                $null_keys[] = $key;
178
                continue;
179
            }
180
181 2
            if (is_null($value))
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
182
                $value = "NULL";
183 2
            elseif ($value instanceof SQLFunction)
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
184
                $value = $value->getStatement();
185
            else {
0 ignored issues
show
Coding Style introduced by
Blank line found at start of control structure
Loading history...
186
187
                switch ($driver)
188
                {
189 2
                    case 'Oci8':
190
                        $bind_values[":$k"] = $value;
191
                        $value = ":$k";
192
                        break;
193
194 2
                    case 'Mysqli' || 'Sqlsrv':
195 2
                        $bind_values[] = $value;
196 2
                        $value = "?";
197 2
                        break;
198
                }
199
            }
200
201 2
            $data[$key] = $value;
202
        }
203
204 2
        foreach ($null_keys as $key)
205
        {
206
            unset($data[$key]);
207
        }
208
209 2
        $cols = implode(",\r\n\t", array_keys($data));
210 2
        $vals = implode(",\r\n\t", array_values($data));
211
212 2
        $table = $this->entity->getTableName();
213
214 2
        $sql = "INSERT INTO {$table} \r\n(\r\n\t$cols\r\n) \r\nVALUES \r\n(\r\n\t$vals\r\n)";
215
216 2
        $this->lastQuery = $sql;
217 2
        $this->lastValues = $bind_values;
218
219 2
        return $this->getDb()->execute($sql, $bind_values);
220
    }
221
222
    /**
223
     * Update statement
224
     *
225
     * @param array $set
226
     * @param array $where
227
     *
228
     * @throws RuntimeException from internal execute()
229
     * @throws LogicException
230
     * @throws Exception\SecurityException
231
     *
232
     * @return resource|object
233
     */
234 4
    public function update(Array $set, Array $where)
0 ignored issues
show
Coding Style introduced by
As per coding-style, PHP keywords should be in lowercase; expected array, but found Array.
Loading history...
235
    {
236 4
        $parsed_set = [];
237
238 4
        if (!count($set))
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
239 1
            throw new \LogicException("You cannot update rows without SET clause");
240
241 3
        if (!count($where))
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
242 1
            throw new Exception\SecurityException("You cannot update rows without WHERE clause!");
243
244 2
        $bind_values = [];
245
246 2
        $driver = $this->getDb()->getDriverName();
247
248 2
        $k = 0;
249
250 2
        foreach ($set as $key => $value)
251
        {
252 2
            $k++;
253
254 2
            if (is_null($value))
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
255
                $parsed_set[] = "$key = NULL";
256 2
            elseif ($value instanceof SQLFunction)
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
257
                $parsed_set[] = "$key = " . $value->getStatement();
258 2
            elseif (is_array($value))
259
            {
260
                $parsed_in = [];
261
262
                foreach ($value as $in_value)
263
                {
264
                    switch ($driver)
265
                    {
266
                        case 'Oci8':
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
267
268
                            # [POSSIBLE BUG] - To Future revision (What about non-string values ?)
269
                            if (is_string($in_value))
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
270
                                $parsed_in[] = ":$k";
271
272
                            $bind_values[":$k"] = $in_value;
273
                            break;
274
275
                        case 'Mysqli' || 'Sqlsrv':
276
                            $parsed_in[] = "?";
277
                            $bind_values[] = $in_value;
278
                            break;
279
                    }
280
281
                    $k++;
282
                }
283
284
                $parsed_set[] = "$key IN (" . implode(", ", $parsed_in) . ")";
285
            }
286
            else
0 ignored issues
show
Coding Style introduced by
Expected 1 space after ELSE keyword; newline found
Loading history...
287
            {
288
                switch ($driver)
289
                {
290 2
                    case 'Oci8':
291
                        $parsed_set[] = "$key = :$k";
292
                        $bind_values[":$k"] = $value;
293
                        break;
294
295 2
                    case 'Mysqli' || 'Sqlsrv':
296 2
                        $parsed_set[] = "$key = ?";
297 2
                        $bind_values[] = $value;
298 2
                        break;
299
                }
300
            }
301
        }
302
303 2
        $parsed_set = implode(",\r\n\t", $parsed_set);
304
305 2
        $parsed_where = [];
306
307 2
        foreach ($where as $key => $value)
308
        {
309 2
            $k++;
310
311 2
            if (is_null($value))
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
312
                $parsed_where[] = "$key IS NULL";
313 2
            elseif ($value instanceof SQLFunction)
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
314
                $parsed_where[] = "$key = " . $value->getStatement();
315 2
            elseif (is_array($value))
316
            {
317
                $parsed_in = [];
318
319
                foreach ($value as $in_value)
320
                {
321
                    switch ($driver)
322
                    {
323
                        case 'Oci8':
324
                            $parsed_in[] = ":$k";
325
                            $bind_values[":$k"] = $in_value;
326
                            break;
327
328
                        case 'Mysqli' || 'Sqlsrv':
329
                            $parsed_in[] = "?";
330
                            $bind_values[] = $in_value;
331
                            break;
332
                    }
333
334
                    $k++;
335
                }
336
337
                $parsed_where[] = "$key IN (" . implode(", ", $parsed_in) . ")";
338
            }
339
            else
0 ignored issues
show
Coding Style introduced by
Expected 1 space after ELSE keyword; newline found
Loading history...
340
            {
341
                switch ($driver)
342
                {
343 2
                    case 'Oci8':
344
                        $parsed_where[] = "$key = :$k";
345
                        $bind_values[":$k"] = $value;
346
                        break;
347
348 2
                    case 'Mysqli' || 'Sqlsrv':
349 2
                        $parsed_where[] = "$key = ?";
350 2
                        $bind_values[] = $value;
351 2
                        break;
352
                }
353
            }
354
        }
355
356 2
        $parsed_where = implode(" AND\r\n\t", $parsed_where);
357
358 2
        $table = $this->entity->getTableName();
359
360 2
        $sql = "UPDATE {$table} \r\nSET \r\n\t$parsed_set \r\nWHERE \r\n\t$parsed_where";
361
362 2
        $this->lastQuery = $sql;
363 2
        $this->lastValues = $bind_values;
364
365 2
        return $this->getDb()->execute($sql, $bind_values);
366
    }
367
368
    /**
369
     * Delete statement
370
     *
371
     * @param array $where
372
     *
373
     * @throws RuntimeException from internal execute()
374
     * @throws Exception\SecurityException
375
     *
376
     * @return resource|object
377
     */
378 3
    public function delete(Array $where)
0 ignored issues
show
Coding Style introduced by
As per coding-style, PHP keywords should be in lowercase; expected array, but found Array.
Loading history...
379
    {
380 3
        if (count($where))
381
        {
382 2
            $parsed_where = [];
383
384 2
            $bind_values = [];
385
386 2
            $driver = $this->getDb()->getDriverName();
387
388 2
            $k = 0;
389
390 2
            foreach ($where as $key => $value)
391
            {
392 2
                $k++;
393
394 2
                if (is_null($value))
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
395
                    $parsed_where[] = "$key IS NULL";
396 2
                elseif ($value instanceof SQLFunction)
0 ignored issues
show
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
397
                    $parsed_where[] = "$key = " . $value->getStatement();
398 2
                elseif (is_array($value))
399
                {
400
                    $parsed_in = [];
401
402
                    foreach ($value as $in_value)
403
                    {
404
                        switch ($driver)
405
                        {
406
                            case 'Oci8':
407
                                $parsed_in[] = ":$k";
408
                                $bind_values[":$k"] = $in_value;
409
                                break;
410
411
                            case 'Mysqli' || 'Sqlsrv':
412
                                $parsed_in[] = "?";
413
                                $bind_values[] = $in_value;
414
                                break;
415
                        }
416
417
                        $k++;
418
                    }
419
420
                    $parsed_where[] = "$key IN (" . implode(", ", $parsed_in) . ")";
421
                }
422
                else
0 ignored issues
show
Coding Style introduced by
Expected 1 space after ELSE keyword; newline found
Loading history...
423
                {
424
                    switch ($driver)
425
                    {
426 2
                        case 'Oci8':
427
                            $parsed_where[] = "$key = :$k";
428
                            $bind_values[":$k"] = $value;
429
                            break;
430
431 2
                        case 'Mysqli' || 'Sqlsrv':
432 2
                            $parsed_where[] = "$key = ?";
433 2
                            $bind_values[] = $value;
434 2
                            break;
435
                    }
436
                }
437
            }
438
439 2
            $where = "\r\nWHERE \r\n\t" . implode(" AND\r\n\t", $parsed_where);
440
        }
441
        else
0 ignored issues
show
Coding Style introduced by
Expected 1 space after ELSE keyword; newline found
Loading history...
Coding Style Best Practice introduced by
It is generally a best practice to always use braces with control structures.

Adding braces to control structures avoids accidental mistakes as your code changes:

// Without braces (not recommended)
if (true)
    doSomething();

// Recommended
if (true) {
    doSomething();
}
Loading history...
442 1
            throw new Exception\SecurityException("You cannot delete rows without WHERE clause!. Use TRUNCATE statement instead.");
443
444 2
        $table = $this->entity->getTableName();
445
446 2
        $sql = "DELETE FROM {$table} $where";
447
448 2
        $this->lastQuery = $sql;
449 2
        $this->lastValues = $bind_values;
450
451 2
        return $this->getDb()->execute($sql, $bind_values);
452
    }
453
}