Passed
Push — master ( fd6afc...38d253 )
by Dāvis
02:50
created

QuickInsertRepository::persist()   D

Complexity

Conditions 20
Paths 252

Size

Total Lines 68
Code Lines 44

Duplication

Lines 3
Ratio 4.41 %

Importance

Changes 0
Metric Value
cc 20
eloc 44
nc 252
nop 6
dl 3
loc 68
rs 4.2686
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace Sludio\HelperBundle\Script\Repository;
4
5
class QuickInsertRepository
6
{
7
    private static $mock = [];
8
    private static $metadata = [];
9
    private static $tableName;
10
11
    public static $entityManager;
12
    public static $connection;
13
14
    public static function init($noFkCheck = false, $manager = null)
15
    {
16
        if (self::$connection) {
17
            return;
18
        }
19
        global $kernel;
20
21
        if ('AppCache' === get_class($kernel)) {
22
            $kernel = $kernel->getKernel();
23
        }
24
        $container = $kernel->getContainer();
25
26
        $manager = $manager ?: $container->getParameter('sludio_helper.entity.manager');
27
        self::$entityManager = $container->get('doctrine')->getManager($manager);
28
        self::$connection = self::$entityManager->getConnection();
29
30
        if (!$noFkCheck) {
31
            $sth = self::$connection->prepare('SET FOREIGN_KEY_CHECKS = 0');
32
            $sth->execute();
33
        }
34
    }
35
36
    public static function close($noFkCheck = false)
37
    {
38
        if (!$noFkCheck) {
39
            $sth = self::$connection->prepare('SET FOREIGN_KEY_CHECKS = 1');
40
            $sth->execute();
41
        }
42
    }
43
44
    public static function isEmpty($variable)
45
    {
46
        $result = true;
47
48
        if (is_array($variable) && count($variable) > 0) {
49
            foreach ($variable as $value) {
50
                $result = $result && self::isEmpty($value);
51
            }
52
        } else {
53
            $result = empty($variable);
54
        }
55
56
        return $result;
57
    }
58
59
    private static function extract($object)
60
    {
61
        self::init(false);
62
        $data = self::extractExt($object, self::$entityManager);
63
64
        self::$mock = $data['mock'];
65
        self::$tableName = $data['table'];
66
        self::$metadata[$data['table']] = $data['meta'];
67
    }
68
69
    public static function extractExt($object, $entityManager)
70
    {
71
        $metadata = $entityManager->getClassMetadata(get_class($object));
72
73
        $fields = $metadata->getFieldNames();
74
        $columns = $metadata->getColumnNames();
75
        $table = $metadata->getTableName();
76
77
        $result = [];
78
        foreach ($fields as $key => $field) {
79
            foreach ($columns as $key2 => $column) {
80
                if ($key === $key2) {
81
                    $result[$table][$field] = $column;
82
                }
83
            }
84
        }
85
86
        $data = [
87
            'mock' => $result,
88
            'table' => $table,
89
            'meta' => $metadata,
90
        ];
91
92
        return $data;
93
    }
94
95
    private static function buildExtra($extra)
96
    {
97
        $methods = [
98
            'GROUP BY',
99
            'HAVING',
100
            'ORDER BY',
101
        ];
102
        $sql = '';
103
104
        foreach ($methods as $method) {
105
            if (isset($extra[$method])) {
106
                $sql .= ' '.$method.' ';
107
                if (is_array($extra[$method])) {
108
                    foreach ($extra[$method] as $group) {
109
                        $sql .= $group.' ';
110
                    }
111
                } else {
112
                    $sql .= $extra[$method].' ';
113
                }
114
            }
115
        }
116
117
        if (isset($extra['LIMIT'])) {
118
            if (is_array($extra['LIMIT'])) {
119
                if (isset($extra['LIMIT'][1])) {
120
                    $offset = $extra['LIMIT'][0];
121
                    $limit = $extra['LIMIT'][1];
122
                } else {
123
                    $offset = 0;
124
                    $limit = $extra['LIMIT'][0];
125
                }
126
                $sql .= 'LIMIT '.$offset.', '.$limit;
127
            }
128
        }
129
130
        $sql = str_replace('  ', ' ', $sql);
131
132
        return $sql;
133
    }
134
135
    private static function buildWhere($tableName, $where)
136
    {
137
        $whereSql = $fvalue = $fkey = '';
138
        if ($where && is_array($where)) {
139
            $skip = false;
140
            foreach ($where as $key => $value) {
141
                $fkey = $key;
142
                if (is_array($value)) {
143
                    $skip = true;
144
                    $fvalue = trim($value[0]);
145
                } else {
146
                    $fvalue = trim($value);
147
                }
148
                break;
149
            }
150 View Code Duplication
            if (!$skip && isset(self::$mock[$tableName][$fkey])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
151
                if (is_numeric($fvalue)) {
152
                    $whereSql .= ' WHERE '.self::$mock[$tableName][$fkey]." = $fvalue";
153
                } else {
154
                    $whereSql .= ' WHERE '.self::$mock[$tableName][$fkey]." = '".addslashes(trim($fvalue))."'";
155
                }
156
            } else {
157
                if (!$skip && is_numeric($fvalue)) {
158
                    $whereSql .= ' WHERE '.$fkey." = $fvalue";
159
                } elseif (!$skip && !is_numeric($fvalue)) {
160
                    $whereSql .= ' WHERE '.$fkey." = '".addslashes(trim($fvalue))."'";
161
                } elseif ($skip && is_numeric($fkey)) {
162
                    $whereSql .= " WHERE $fvalue";
163
                }
164
            }
165
            unset($where[$fkey]);
166
            if ($where && is_array($where)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $where of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
167
                foreach ($where as $key => $value) {
168
                    $skip = is_array($value);
169 View Code Duplication
                    if (!$skip && isset(self::$mock[$tableName][$key])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
170
                        if (is_numeric($value)) {
171
                            $whereSql .= ' AND '.self::$mock[$tableName][$key]." = $value";
172
                        } else {
173
                            $whereSql .= ' AND '.self::$mock[$tableName][$key]." = '".addslashes(trim($value))."'";
174
                        }
175
                    } else {
176
                        if (!$skip && is_numeric($value)) {
177
                            $whereSql .= ' AND '.$key." = $value";
178
                        } elseif (!$skip && !is_numeric($value)) {
179
                            $whereSql .= ' AND '.$key." = '".addslashes(trim($value))."'";
180
                        } elseif ($skip && is_numeric($key)) {
181
                            $whereSql .= " AND {$value[0]}";
182
                        }
183
                    }
184
                }
185
            }
186
        }
187
188
        return $whereSql;
189
    }
190
191
    private static function getTable(&$object, &$tableName, &$columns, &$type)
192
    {
193
        if (is_object($object)) {
194
            self::extract($object);
195
            $tableName = self::$tableName;
196
            $columns = self::$mock[$tableName] ?: [];
197
            $type = 'object';
198
        } else {
199
            $tableName = $object['table_name'];
200
            unset($object['table_name']);
201
            $type = 'table';
202
            $columns = array_keys($object) ?: [];
203
        }
204
    }
205
206
    public static function findNextId($tableName, &$out = null)
207
    {
208
        $result = self::get(['table_name' => 'information_schema.tables'], true, [
209
            'table_name' => $tableName,
210
            ['table_schema = DATABASE()'],
211
        ], true, ['AUTO_INCREMENT'], null, [], $out);
212
213
        if ($result) {
214
            return $result;
215
        }
216
217
        return 1;
218
    }
219
220
    public static function findNextIdExt($object, $entityManager, &$out = null)
221
    {
222
        self::init(true);
223
        $data = self::extractExt($object, $entityManager);
224
225
        return self::findNextId($data['table'], $out);
226
    }
227
228
    public static function get($object, $one = false, $where = [], $noFkCheck = true, $fields = [], $manager = null, $extra = [], &$out = null)
0 ignored issues
show
Coding Style introduced by
This method's name is shorter than the configured minimum length of 4 characters.

Even though PHP does not care about the name of your methods, it is generally a good practice to choose method names which can be easily understood by other human readers.

Loading history...
229
    {
230
        self::init(true, $manager);
231
        self::getTable($object, $tableName, $columns, $type);
232
233
        $whereSql = self::buildWhere($tableName, $where);
234
        $select = (isset($extra['MODE']) ? 'SELECT '.$extra['MODE'] : 'SELECT').' ';
235
        if (!$fields) {
236
            $sql = $select.'id FROM '.$tableName.' '.$whereSql;
237
        } else {
238
            $sql = $select.(implode(', ', $fields)).' FROM '.$tableName.' '.$whereSql;
239
        }
240
        if (!empty($extra)) {
241
            $extraSql = self::buildExtra($extra);
242
            $sql .= $extraSql;
243
        }
244
        if ($out) {
245
            $out = $sql;
246
        }
247
        $sth = self::$connection->prepare($sql);
248
        $sth->execute();
249
        $result = $sth->fetchAll();
250
        if ($one && $result) {
251
            if (!$fields) {
252
                return intval($result[0]['id']);
253
            } else {
254
                if (count($fields) === 1 && $fields[0] !== '*') {
255
                    return $result[0][$fields[0]];
256
                } else {
257
                    return $result[0];
258
                }
259
            }
260
        }
261
262
        self::close(true);
263
        if ($one || !$result) {
264
            return null;
265
        }
266
267
        $field = null;
268
        if (!$fields) {
269
            $field = 'id';
270
        } elseif (count($fields) === 1 && $fields[0] !== '*') {
271
            $field = $fields[0];
272
        }
273
274
        if ($field) {
275
            foreach ($result as &$res) {
276
                $res = $res[$field];
277
            }
278
        }
279
280
        return $result;
281
    }
282
283
    private static function value($object, $variable, $type)
284
    {
285
        if ($type === 'object') {
286
            return $object->{'get'.ucfirst($variable)}();
287
        } else {
288
            return $object[$variable];
289
        }
290
    }
291
292
    public static function persist($object, $full = false, $extraFields = [], $noFkCheck = false, $manager = null, &$out = null)
293
    {
294
        self::init($noFkCheck, $manager);
295
        self::getTable($object, $tableName, $columns, $type);
296
297
        $id = self::findNextId($tableName);
298
        $keys = [];
299
        $values = [];
300
301 View Code Duplication
        if (!empty($extraFields) && isset($extraFields[$tableName])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
302
            $columns = array_merge($columns, $extraFields[$tableName]);
303
        }
304
305
        $idd = null;
306
        foreach ($columns as $value => $key) {
307
            $variable = null;
308
            if (!is_array($key) && !is_array($value)) {
309
                $value = self::value($object, $value, $type);
310
                if ($value instanceof \DateTime) {
311
                    $variable = "'".addslashes(trim($value->format('Y-m-d H:i:s')))."'";
312
                } else {
313
                    $variable = "'".addslashes(trim($value))."'";
314
                }
315
                if (trim($variable) === '' || trim($variable) === "''" || (is_numeric($variable) && $variable === 0)) {
316
                    $variable = null;
317
                }
318
                if ($variable !== null) {
319
                    $values[] = $variable;
320
                    $keys[] = $key;
321
                    if ($key === 'id') {
322
                        $idd = $value;
323
                    }
324
                }
325
            }
326
        }
327
328
        $sql = null;
329
        if (!$full && !self::isEmpty($values)) {
330
            $sql = '
331
                INSERT INTO
332
                    '.$tableName.'
333
                        (id, '.implode(',', $keys).")
334
                VALUES
335
                    ({$id},".implode(',', $values).')
336
            ';
337
        } elseif ($full && !self::isEmpty($values)) {
338
            $id = $idd;
339
            $sql = '
340
                INSERT INTO
341
                    '.$tableName.'
342
                        ('.implode(',', $keys).")
343
                VALUES
344
                    (".implode(',', $values).')
345
            ';
346
        } else {
347
            $id = null;
348
        }
349
        if ($sql !== null && $id !== null) {
350
            if ($out) {
351
                $out = $sql;
352
            }
353
            $sth = self::$connection->prepare($sql);
354
            $sth->execute();
355
        }
356
357
        self::close($noFkCheck);
358
359
        return $id;
360
    }
361
362
    public static function update($id, $object, $extraFields = [], $noFkCheck = false, $manager = null, &$out = null)
363
    {
364
        self::init($noFkCheck, $manager);
365
        self::getTable($object, $tableName, $columns, $type);
366
367
        $result = self::get($tableName, true, ['id' => $id], true, ['*']);
368
        unset($result['id']);
369
370
        $data = [];
371
372 View Code Duplication
        if (!empty($extraFields) && isset($extraFields[$tableName])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
373
            $columns = array_merge($columns, $extraFields[$tableName]);
374
        }
375
376
        $flip = array_flip($columns);
377
        if ($type === 'object') {
378
            if ($id) {
379
                foreach ($result as $key => $value) {
380 View Code Duplication
                    if ($object->{'get'.ucfirst($flip[$key])}() !== $value) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
381
                        $data[$columns[$flip[$key]]] = $object->{'get'.ucfirst($flip[$key])}();
382
                    }
383
                }
384
            } else {
385
                foreach ($result as $key => $value) {
386
                    if ($object->{'get'.ucfirst($flip[$key])}() !== null) {
387 View Code Duplication
                        if ($object->{'get'.ucfirst($flip[$key])}() !== $value) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
388
                            $data[$columns[$flip[$key]]] = $object->{'get'.ucfirst($flip[$key])}();
389
                        }
390
                    }
391
                }
392
            }
393
        } else {
394
            foreach ($result as $key => $value) {
395
                if (isset($object[$key]) && $object[$key] !== $value) {
396
                    $data[$key] = $extraFields[$key];
397
                }
398
            }
399
400
        }
401
402
        if ($data) {
403
            $sql = "
404
                UPDATE
405
                    ".$tableName."
406
                SET
407
408
            ";
409
            foreach ($data as $key => $value) {
410
                $meta = self::$metadata[$tableName]->getFieldMapping($flip[$key]);
411
                $meta = $meta['type'];
412
                if (in_array($meta, [
413
                    'boolean',
414
                    'integer',
415
                    'longint',
416
                ])) {
417
                    $value = intval($value);
418
                } else {
419
                    $value = "'".addslashes(trim($value))."'";
420
                }
421
                $sql .= " ".$key." = ".$value.",";
422
            }
423
            $sql = substr($sql, 0, -1);
424
            $sql .= " WHERE id = ".$id;
425
            if ($out) {
426
                $out = $sql;
427
            }
428
429
            $sthu = self::$connection->prepare($sql);
430
            $sthu->execute();
431
        }
432
433
        self::close($noFkCheck);
434
    }
435
436
    public static function delete($object, $where = [], $noFkCheck = false, $manager = null, &$out = null)
437
    {
438
        self::init($noFkCheck, $manager);
439
        self::getTable($object, $tableName, $columns, $type);
440
441
        $whereSql = self::buildWhere($tableName, $where);
442
        $sql = 'DELETE FROM '.$tableName.' '.$whereSql;
443
        if ($out) {
444
            $out = $sql;
445
        }
446
        $sth = self::$connection->prepare($sql);
447
        $sth->execute();
448
449
        self::close($noFkCheck);
450
    }
451
452
    public static function link($object, $data, $noFkCheck = false, $manager = null, &$out = null)
453
    {
454
        self::init($noFkCheck, $manager);
455
        self::getTable($object, $tableName, $columns, $type);
456
457
        if ($object && $data) {
458
            $keys = $values = [];
459
            foreach ($data as $key => $value) {
460
                $keys[] = $key;
461
                $values[] = $value;
462
            }
463
            $sql = "
464
                INSERT IGNORE INTO
465
                    ".$tableName."
466
                        (".implode(',', $keys).")
467
                VALUES
468
                    (".implode(',', $values).")
469
            ";
470
            if ($out) {
471
                $out = $sql;
472
            }
473
            $sth = self::$connection->prepare($sql);
474
            $sth->execute();
475
        }
476
477
        self::close($noFkCheck);
478
    }
479
}
480