Passed
Push — master ( 55c7d5...aed71d )
by Dāvis
03:01
created

QuickInsertRepository   F

Complexity

Total Complexity 75

Size/Duplication

Total Lines 352
Duplicated Lines 3.69 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
dl 13
loc 352
rs 2.3076
c 2
b 0
f 0
wmc 75

16 Methods

Rating   Name   Duplication   Size   Complexity  
C update() 0 42 8
B init() 0 18 5
A runSQL() 0 10 2
C buildExtra() 0 38 8
A value() 0 16 4
A extract() 0 9 1
A findNextIdExt() 0 6 1
A findNextId() 0 12 2
A link() 6 6 1
D persist() 0 41 9
C get() 0 29 11
B extractExt() 0 29 5
A close() 0 4 2
A delete() 6 6 1
B getTable() 0 17 5
C buildWhere() 0 24 10

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like QuickInsertRepository 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 QuickInsertRepository, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace Sludio\HelperBundle\Script\Repository;
4
5
use Sludio\HelperBundle\Script\Utils\Helper;
6
7
class QuickInsertRepository
8
{
9
    private static $mock = [];
10
    private static $metadata = [];
11
    private static $tableName;
12
    private static $identifier;
13
14
    public static $entityManager;
15
    public static $connection;
16
17
    public static function init($noFkCheck = false, $manager = null)
18
    {
19
        if (self::$connection) {
20
            return;
21
        }
22
        global $kernel;
23
24
        if ('AppCache' === get_class($kernel)) {
25
            $kernel = $kernel->getKernel();
26
        }
27
        $container = $kernel->getContainer();
28
29
        $manager = $manager ?: $container->getParameter('sludio_helper.entity.manager');
30
        self::$entityManager = $container->get('doctrine')->getManager($manager);
31
        self::$connection = self::$entityManager->getConnection();
32
33
        if (!$noFkCheck) {
34
            self::runSQL('SET FOREIGN_KEY_CHECKS = 0');
35
        }
36
    }
37
38
    public static function close($noFkCheck = false)
39
    {
40
        if (!$noFkCheck) {
41
            self::runSQL('SET FOREIGN_KEY_CHECKS = 1');
42
        }
43
    }
44
45
    private static function extract($object)
46
    {
47
        self::init(false);
48
        $data = self::extractExt($object, self::$entityManager);
49
50
        self::$mock = $data['mock'];
51
        self::$tableName = $data['table'];
52
        self::$metadata[$data['table']] = $data['meta'];
53
        self::$identifier = $data['identifier'];
54
    }
55
56
    public static function extractExt($object, $entityManager)
57
    {
58
        $metadata = $entityManager->getClassMetadata(get_class($object));
59
60
        $fields = $metadata->getFieldNames();
61
        $columns = $metadata->getColumnNames();
62
        $table = $metadata->getTableName();
63
        $identifier = null;
64
65
        $result = [];
66
        foreach ($fields as $key => $field) {
67
            foreach ($columns as $key2 => $column) {
68
                if ($key === $key2) {
69
                    $result[$table][$field] = $column;
70
                    if($field === $metadata->getIdentifier()[0]){
71
                        $identifier = $column;
72
                    }
73
                }
74
            }
75
        }
76
77
        $data = [
78
            'mock' => $result,
79
            'table' => $table,
80
            'meta' => $metadata,
81
            'identifier' => $identifier
82
        ];
83
84
        return $data;
85
    }
86
87
    private static function buildExtra($extra)
88
    {
89
        $methods = [
90
            'GROUP BY',
91
            'HAVING',
92
            'ORDER BY',
93
        ];
94
        $sql = '';
95
96
        foreach ($methods as $method) {
97
            if (isset($extra[$method])) {
98
                $sql .= ' '.$method.' ';
99
                if (is_array($extra[$method])) {
100
                    foreach ($extra[$method] as $group) {
101
                        $sql .= $group.' ';
102
                    }
103
                } else {
104
                    $sql .= $extra[$method].' ';
105
                }
106
            }
107
        }
108
109
        if (isset($extra['LIMIT'])) {
110
            if (is_array($extra['LIMIT'])) {
111
                if (isset($extra['LIMIT'][1])) {
112
                    $offset = $extra['LIMIT'][0];
113
                    $limit = $extra['LIMIT'][1];
114
                } else {
115
                    $offset = 0;
116
                    $limit = $extra['LIMIT'][0];
117
                }
118
                $sql .= 'LIMIT '.$offset.', '.$limit;
119
            }
120
        }
121
122
        $sql = str_replace('  ', ' ', $sql);
123
124
        return $sql;
125
    }
126
127
    private static function buildWhere($tableName, $where)
128
    {
129
        $whereSql = '';
130
        if (is_array($where) && !empty($where)) {
131
            reset($where);
132
            $first = key($where);
133
            $path = ' WHERE ';
134
            foreach ($where as $key => $value) {
135
                if (!is_array($value) && isset(self::$mock[$tableName][$key])) {
136
                    $whereSql .= $path.self::$mock[$tableName][$key]." = ".(is_numeric($value) ? $value : "'".addslashes(trim($value))."'");
137
                } else {
138
                    if (is_array($value)) {
139
                        $whereSql .= $path.$value[0];
140
                    } else {
141
                        $whereSql .= $path.$key." = ".(is_numeric($value) ? $value : "'".addslashes(trim($value))."'");
142
                    }
143
                }
144
                if ($key === $first) {
145
                    $path = ' AND ';
146
                }
147
            }
148
        }
149
150
        return $whereSql;
151
    }
152
153
    private static function getTable(&$object, &$tableName, &$columns, &$type, $noFkCheck = true, $manager = null, $extraFields = [])
154
    {
155
        self::init($noFkCheck, $manager);
156
        if (is_object($object)) {
157
            self::extract($object);
158
            $tableName = self::$tableName;
159
            $columns = self::$mock[$tableName] ?: [];
160
            $type = 'object';
161
        } else {
162
            $tableName = $object['table_name'];
163
            unset($object['table_name']);
164
            $type = 'table';
165
            $columns = array_keys($object) ?: [];
166
        }
167
168
        if (isset($extraFields[$tableName])) {
169
            $columns = array_merge($columns, $extraFields[$tableName]);
170
        }
171
    }
172
173
    public static function findNextId($tableName)
174
    {
175
        $result = self::get(['table_name' => 'information_schema.tables'], true, [
176
            'table_name' => $tableName,
177
            ['table_schema = DATABASE()'],
178
        ], true, ['AUTO_INCREMENT'], null, []);
179
180
        if ($result) {
181
            return $result;
182
        }
183
184
        return 1;
185
    }
186
187
    public static function findNextIdExt($object, $entityManager = null)
188
    {
189
        self::init(true);
190
        $data = self::extractExt($object, $entityManager);
191
192
        return self::findNextId($data['table']);
193
    }
194
195
    public static function runSQL($sql, $noFkCheck = true, $manager = null)
196
    {
197
        $sql = trim(preg_replace('/\s+/', ' ', $sql));
198
        self::init($noFkCheck, $manager);
199
        $sth = self::$connection->prepare($sql);
200
        $sth->execute();
201
202
        self::close($noFkCheck);
203
        if (substr($sql, 0, 6) === "SELECT") {
204
            return $sth->fetchAll();
205
        }
206
    }
207
208
    public static function get($object, $one = false, $where = [], $noFkCheck = true, $fields = [], $manager = null, $extra = [])
209
    {
210
        self::getTable($object, $tableName, $columns, $type, $noFkCheck, $manager);
211
212
        $select = (isset($extra['MODE']) ? 'SELECT '.$extra['MODE'] : 'SELECT').' ';
213
        $fields = $fields ?: ['id'];
214
        $sql = $select.(implode(', ', $fields)).' FROM '.$tableName.self::buildWhere($tableName, $where).self::buildExtra($extra);
215
216
        $result = self::runSQL($sql) ?: null;
217
218
        if ($result) {
219
            $field = null;
220
            if (count($fields) === 1 && $fields[0] !== '*') {
221
                $field = $fields[0];
222
            }
223
            if ($field) {
224
                if (!$one) {
225
                    foreach ($result as &$res) {
226
                        $res = $res[$field];
227
                    }
228
                } else {
229
                    $result = $result[0][$field];
230
                }
231
            } elseif ($one) {
232
                $result = $result[0];
233
            }
234
        }
235
236
        return $result;
237
    }
238
239
    private static function value($object, $variable, $type, $check = true)
240
    {
241
        $value = null;
242
        if ($type === 'object') {
243
            $value = $object->{'get'.ucfirst(Helper::toCamelCase($variable))}();
244
        } else {
245
            if (isset($object[$variable])) {
246
                $value = $object[$variable];
247
            }
248
        }
249
250
        if ($check) {
251
            Helper::variable($value);
252
        }
253
254
        return $value;
255
    }
256
257
    public static function persist($object, $full = false, $extraFields = [], $noFkCheck = false, $manager = null)
258
    {
259
        self::getTable($object, $tableName, $columns, $type, $noFkCheck, $manager, $extraFields);
260
261
        $id = self::findNextId($tableName);
262
        $data = [];
263
264
        $idd = null;
265
        foreach ($columns as $value => $key) {
266
            if (!is_array($key) && !is_array($value)) {
267
                $value = self::value($object, $value, $type);
268
                if ($value !== null) {
269
                    $data[$key] = $value;
270
                    if ($key === self::$identifier) {
271
                        $idd = $value;
272
                    }
273
                }
274
            }
275
        }
276
277
        if (!$full) {
278
            $data[self::$identifier] = $id;
279
        } else {
280
            $id = $idd;
281
        }
282
283
        if (Helper::isEmpty($data) && $id !== null) {
284
            return null;
285
        }
286
287
        $sql = '
288
            INSERT INTO
289
                '.$tableName.'
290
                    ('.implode(',', array_keys($data)).')
291
            VALUES
292
                ('.implode(',', array_values($data)).')
293
        ';
294
295
        self::runSQL($sql);
296
297
        return $id;
298
    }
299
300
    public static function update($id, $object, $extraFields = [], $noFkCheck = false, $manager = null)
301
    {
302
        self::getTable($object, $tableName, $columns, $type, $noFkCheck, $manager, $extraFields);
303
304
        $result = self::get(['table_name' => $tableName], true, ['id' => $id], true, ['*']);
305
        unset($result['id']);
306
        $data = [];
307
308
        $flip = array_flip($columns);
309
        foreach ($result as $key => $value) {
310
            $content = self::value($object, $key, $type, false);
311
            if ($content !== $value) {
312
                $data[$key] = $content;
313
            }
314
            if (!$id && $content === null) {
315
                unset($data[$key]);
316
            }
317
        }
318
319
        if ($data) {
320
            $sql = '
321
                UPDATE
322
                    '.$tableName.'
323
                SET
324
325
            ';
326
            foreach ($data as $key => $value) {
327
                $meta = self::$metadata[$tableName]->getFieldMapping($flip[$key])['type'];
328
                if (in_array($meta, [
329
                    'boolean',
330
                    'integer',
331
                    'longint',
332
                ])) {
333
                    $value = intval($value);
334
                } else {
335
                    $value = "'".addslashes(trim($value))."'";
336
                }
337
                $sql .= " ".$key." = ".$value.",";
338
            }
339
            $sql = substr($sql, 0, -1).' WHERE id = '.$id;
340
341
            self::runSQL($sql);
342
        }
343
    }
344
345 View Code Duplication
    public static function delete($object, $where = [], $noFkCheck = false, $manager = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
346
    {
347
        self::getTable($object, $tableName, $columns, $type, $noFkCheck, $manager);
348
349
        $sql = 'DELETE FROM '.$tableName.self::buildWhere($tableName, $where);
350
        self::runSQL($sql);
351
    }
352
353 View Code Duplication
    public static function link($object, $data, $noFkCheck = false, $manager = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
354
    {
355
        self::getTable($object, $tableName, $columns, $type, $noFkCheck, $manager);
356
357
        $data['table_name'] = $tableName;
358
        self::persist($data, true, [], $noFkCheck, $manager);
359
    }
360
}
361