JsonExtractor::getTablesArray()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Lifeeka\JSQL\Extractor;
4
5
use Lifeeka\JSQL\Helpers\Json;
6
7
/**
8
 * Class JsonExtractor.
9
 */
10
class JsonExtractor
11
{
12
    public $json;
13
14
    private $table = [];
15
    private $data = [];
16
    private $foreign = [];
17
18
    public $need_id = true;
19
    public $snake_case_column = true;
20
    public $snake_case_table = true;
21
    public $main_table_name = "main";
22
23
    /**
24
     * JsonExtractor constructor.
25
     * @param Json $json
26
     * @param $mainTableName
27
     */
28
    public function __construct(Json $json, $mainTableName)
29
    {
30
        $this->json = $json;
31
        $this->main_table_name = $mainTableName;
32
    }
33
34
    /**
35
     * @return array
36
     */
37
    public function getTablesArray()
38
    {
39
        return $this->table;
40
    }
41
42
    /**
43
     * @return array
44
     */
45
    public function getForeignKeyArray()
46
    {
47
        return $this->foreign;
48
    }
49
50
    /**
51
     * @return array
52
     */
53
    public function getDataArray()
54
    {
55
        return $this->data;
56
    }
57
58
59
    /**
60
     * @param bool $data
61
     * @param string $prefix
62
     */
63
    public function toMysqlTables($data = false, $prefix = '')
64
    {
65
        if (!$data) {//if this is not a recursive
66
            $data = $this->json->toObject();
67
        }
68
69
        foreach ($data as $key => $value) {//loop the data
70
71
            $table_name = is_numeric($key) ? $this->main_table_name : $key;
72
73
74
            if (is_array($value) && is_object($value[0])) {//check whether it's a array and it's firs element is a object
75
76
                $table_data = $this->getTable($prefix . $table_name, $value); //get table sql
77
                $this->table[$table_data['name']] = $table_data['column'];
78
79
                $this->toMysqlTables($this->getHighestColumnArray($value), $prefix . $table_name . "_"); //get it inside tables
80
            } elseif (is_array($value) || is_object($value)) {//if it's a array and  firs element is not a object
81
82
                $table_data = $this->getTable($prefix . $table_name, $value);
83
                $this->table[$table_data['name']] = $table_data['column'];
84
            }
85
        }
86
    }
87
88
89
    /**
90
     * @param bool $data
91
     * @param string $prefix
92
     */
93
    public function toMysqlData($data = false, $prefix = '')
94
    {
95
        if (!$data) {//if this is not a recursive
96
            $data = $this->json->toObject();
97
        }
98
        foreach ($data as $table_name => $value) {
99
            if ($this->snake_case_table) {
100
                $table_name = $this->snakeCase($prefix . $table_name);
101
            }
102
            if (is_array($value) && !empty($value) && is_object($value[0])) {//if it's a array and  firs element is not a object
103
                $this->toMysqlData($value, $table_name . '_');
0 ignored issues
show
Bug introduced by
$value of type array is incompatible with the type boolean expected by parameter $data of Lifeeka\JSQL\Extractor\J...xtractor::toMysqlData(). ( Ignorable by Annotation )

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

103
                $this->toMysqlData(/** @scrutinizer ignore-type */ $value, $table_name . '_');
Loading history...
104
            } elseif (is_object($value) || is_array($value)) {
105
                $this->toMysqlData($value, $table_name . '_');
0 ignored issues
show
Bug introduced by
$value of type array|object is incompatible with the type boolean expected by parameter $data of Lifeeka\JSQL\Extractor\J...xtractor::toMysqlData(). ( Ignorable by Annotation )

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

105
                $this->toMysqlData(/** @scrutinizer ignore-type */ $value, $table_name . '_');
Loading history...
106
                $this->getTableData($table_name, $value);
107
            }
108
        }
109
    }
110
111
112
    /**
113
     * @param $table_name
114
     * @param $value
115
     */
116
    public function getTableData($table_name, $value)
117
    {
118
        if (isset($this->table[$table_name])) {
119
            $ColumnList = $this->table[$table_name];
120
121
            $DataItem = [];
122
123
            if (is_object($value)) {
124
                foreach ($ColumnList as $ColumnItem) {
125
                    if ($this->isPropertyExist($value, $ColumnItem['name'])) {
126
                        $CurrentItem = $this->snake_case_column ? $this->objectToSnakeCase($value) : $value;
127
                        $column_name = $ColumnItem['name'];
128
                        $DataItem[$column_name] = $CurrentItem->{$ColumnItem['name']};
129
                    } else {
130
                        $column_name = $ColumnItem['name'];
131
                        $DataItem[$column_name] = null;
132
                    }
133
                }
134
                $this->data[$table_name][] = $DataItem;
135
            } elseif (is_array($value)) {//reference table
136
                foreach ($value as $item_value) {
137
                    $DataItem[] = ['value' => $item_value];
138
                }
139
140
                $this->data[$table_name] = array_merge(($this->data[$table_name] ?? []), $DataItem);
141
            }
142
        }
143
    }
144
145
    /**
146
     * @param $table
147
     * @param $data
148
     * @return array
149
     */
150
    public function getTable($table, $data)
151
    {
152
        $column = $this->getColumn($this->getHighestColumnArray($data), $table);
153
154
        if ($this->snake_case_table) {
155
            $table = $this->snakeCase($table);
156
        }
157
158
        if ($this->snake_case_column) {
159
            return [
160
                'name' => $table,
161
                'column' => array_map(function ($item) {
162
                    return [
163
                        'name' => $this->snakeCase($item['name']),
164
                        'type' => $item['type'],
165
                        'ref' => $item['ref'] ?? null
166
                    ];
167
                }, $column)
168
            ];
169
        } else {
170
            return [
171
                'name' => $table,
172
                'column' => $column
173
            ];
174
        }
175
    }
176
177
178
    /**
179
     * @param $data
180
     * @param $table
181
     * @return array
182
     */
183
    public function getColumn($data, $table)
184
    {
185
        $ForeignKeys = $this->json->getForeignKeys();
186
187
        $Columns = [];
188
189
        if (is_object($data)) {
190
            foreach ($data ?? [] as $Column => $Value) {
191
                if (!is_array($Value) && !is_object($Value) && !empty($Column) && !is_numeric($Column)) {
192
                    if (isset($ForeignKeys[JsonExtractor::snakeCase($table)]) && $ForeignKeys[JsonExtractor::snakeCase($table)]['name'] == JsonExtractor::snakeCase($Column)) {
193
                        $Columns[] = ['name' => $Column, 'type' => 'foreign_key', 'ref' => $ForeignKeys[JsonExtractor::snakeCase($table)]['ref']];
194
                    } elseif ($Column == 'id') {
195
                        $Columns[] = ['name' => $Column, 'type' => 'primary_key'];
196
                    } else {
197
                        $Columns[] = ['name' => $Column, 'type' => gettype($this->getActualDataType($Value, ""))];
198
                    }
199
                }
200
            }
201
        } elseif (is_array($data)) {
202
            $Columns[] = ['name' => 'value', 'type' => gettype($this->getActualDataType($data[0], ""))];
203
        }
204
        return $Columns;
205
    }
206
207
    /**
208
     * @param $data
209
     * @param $column
210
     * @return array
211
     */
212
    public function getData($data, $column)
213
    {
214
        $values = [];
215
216
        $index = 0;
217
        foreach ($data as $row_item) {
218
            foreach ($column as $column_item) {
219
                switch (is_object($row_item)) {
220
                    case true:
221
                        $values[$index][$column_item['name']] = $this->getActualDataType(($row_item->{$column_item['name']}) ?? null, null);
222
                        break;
223
                    case false:
224
                        $values[$index][$column_item['name']] = $this->getActualDataType(($data->{$column_item['name']}) ?? null, null);
225
                        break;
226
                }
227
            }
228
            $index++;
229
        }
230
231
232
        return $values;
233
    }
234
235
    /**
236
     * @param $input
237
     *
238
     * @return string
239
     */
240
    public static function snakeCase($input)
241
    {
242
        preg_match_all('!([A-Z][A-Z0-9]*(?=$|[A-Z][a-z0-9])|[A-Za-z][a-z0-9]+)!', $input, $matches);
243
        $ret = $matches[0];
244
245
        foreach ($ret as &$match) {
246
            $match = $match == strtoupper($match) ? strtolower($match) : lcfirst($match);
247
        }
248
249
        return implode('_', $ret);
250
    }
251
252
    /**
253
     * @param $Object
254
     * @return \stdClass
255
     */
256
    public static function objectToSnakeCase($Object)
257
    {
258
        $ReturnObject = new \stdClass();
259
260
        foreach ($Object as $ObjectAttribute => $ObjectItem) {
261
            $ReturnObject->{JsonExtractor::snakeCase($ObjectAttribute)} = $ObjectItem;
262
        }
263
        return $ReturnObject;
264
    }
265
266
267
    /**
268
     * @param Object $Object
269
     * @param $Attribute
270
     * @return bool
271
     */
272
    public function isPropertyExist($Object, $Attribute)
273
    {
274
        foreach (array_keys(get_object_vars($Object)) as $CurrentAttributeName) {
275
            if ($this->snake_case_column && $this->snakeCase($CurrentAttributeName) == $Attribute) {
276
                return true;
277
            } elseif ($CurrentAttributeName === $Attribute) {
278
                return true;
279
            }
280
        }
281
282
        return false;
283
    }
284
285
286
    /**
287
     * @param $array
288
     * @return bool|mixed
289
     */
290
    public static function getHighestColumnArray($array)
291
    {
292
        if (is_object($array) || (is_array($array) && !is_object($array[0]) && !is_array($array[0]))) {
293
            return $array;
294
        }
295
296
        $Highest = false;
297
        $ColumnCount = false;
298
        $HighestSubCount = false;
299
300
        foreach ($array as $array_item) {
301
            $current_sub = 0;
302
            //check how many array/object have
303
            foreach ($array_item as $SubArrayItem) {
304
                if (is_array($SubArrayItem) || is_object($SubArrayItem)) {
305
                    $current_sub = $current_sub + 2;
306
                }
307
            }
308
            //check how many column have
309
            if ($ColumnCount <= @count($array_item) || !$Highest) {
310
                if ($current_sub > $HighestSubCount || !$Highest) {
311
                    $Highest = $array_item;
312
                    $HighestSubCount = $current_sub;
313
                    $ColumnCount = @count($array_item);
314
                }
315
            }
316
        }
317
318
319
        return $Highest;
320
    }
321
322
    /**
323
     * @param $array
324
     * @return string
325
     */
326
    public static function getStringFromData($array)
327
    {
328
        $String = [];
329
330
        foreach ($array as $item_row) {
331
            $value = [];
332
            foreach ($item_row as $item) {
333
                if (empty($item) && !is_numeric($item)) {
334
                    $value[] = "null";
335
                } elseif (is_numeric($item)) {
336
                    $value[] = $item;
337
                } else {
338
                    $value[] = '"' . addcslashes($item, "W") . '"';
339
                }
340
            }
341
            $String[] = '(' . implode(",", $value) . ')';
342
        }
343
344
        return "values" . implode(", ", $String);
345
    }
346
347
    /**
348
     * @param $array
349
     * @return string
350
     */
351
    public static function getStringFromColumns($array)
352
    {
353
        $String = [];
354
        foreach ($array as $column) {
355
            $String[] = "`" . JsonExtractor::snakeCase($column['name']) . "`";
356
        }
357
358
        return implode(",", $String);
359
    }
360
361
362
    /**
363
     * @param $Data
364
     * @param $empty_val
365
     * @return int|string
366
     */
367
    public static function getActualDataType($Data, $empty_val)
368
    {
369
        $Data = trim($Data);
370
        if (is_numeric($Data)) {
371
            return $Data + 0;
372
        } elseif (empty($Data)) {
373
            return $empty_val;
374
        } else {
375
            return (string)$Data;
376
        }
377
    }
378
}
379