Passed
Push — master ( 7b08a2...d0c126 )
by Supun
03:14
created

JsonExtractor::getData()   B

Complexity

Conditions 5
Paths 5

Size

Total Lines 21
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 13
nc 5
nop 2
dl 0
loc 21
rs 8.7624
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
17
    public $need_id = true;
18
    public $snake_case_column = true;
19
    public $snake_case_table = true;
20
    public $main_table_name = "main";
21
22
    /**
23
     * JsonExtractor constructor.
24
     *
25
     * @param Json $json
26
     */
27
    public function __construct(Json $json)
28
    {
29
        $this->json = $json;
30
    }
31
32
    /**
33
     * @return array
34
     */
35
    public function getTablesArray()
36
    {
37
        return $this->table;
38
    }
39
40
    /**
41
     * @return array
42
     */
43
    public function getDataArray()
44
    {
45
        return $this->data;
46
    }
47
48
49
    /**
50
     * @param bool $data
51
     * @param string $prefix
52
     * @return string
53
     */
54
    public function toMysqlTables($data = false, $prefix = '')
55
    {
56
        if (!$data) {//if this is not a recursive
57
            $data = $this->json->toObject();
58
        }
59
60
61
        foreach ($data as $key => $value) {//loop the data
62
63
            $table_name = is_numeric($key) ? $this->main_table_name : $key;
64
65
            if (is_array($value) && is_object($value[0])) {//check whether it's a array and it's firs element is a object
66
67
                $table_data = $this->getTable($prefix . $table_name, $value);//get table sql
68
                $this->table[$table_data['tables']['name']] = $table_data['tables']['column'];
69
                $this->data[$table_data['data']['table']] = $table_data['data']['data'];
70
71
                $this->toMysqlTables($this->getHighestColumnArray($value), $prefix . $table_name . '_');//get it inside tables
72
            } elseif (is_array($value) || is_object($value)) {//if it's a array and  firs element is not a object
73
74
                $table_data = $this->getTable($prefix . $table_name, $value);
75
                $this->table[$table_data['tables']['name']] = $table_data['tables']['column'];
76
                $this->data[$table_data['data']['table']] = $table_data['data']['data'];
77
            }
78
        }
79
    }
80
81
82
    /**
83
     * @param $table
84
     * @param $data
85
     * @return array
86
     */
87
    public function getTable($table, $data)
88
    {
89
        $column = $this->getColumn($this->getHighestColumnArray($data));
90
91
92
        if ($this->snake_case_table) {
93
            $table = $this->snakeCase($table);
94
        }
95
96
        $table_data = $this->getData($data, $column);
97
98
        $last_columns = $column;
99
        if ($this->need_id && array_search('id', array_column($column, 'name')) === false) {
100
            $last_columns[] = [
101
                'name' => "id",
102
                'type' => "int"
103
            ];
104
        }
105
106
        return [
107
            'tables' => [
108
                'name' => $table,
109
                'column' => $last_columns
110
            ],
111
            'data' => [
112
                'table' => $table,
113
                'data' => $table_data
114
            ]
115
        ];
116
    }
117
118
    /**
119
     * @param $data
120
     *
121
     * @return array
122
     */
123
    public function getColumn($data)
124
    {
125
        $Columns = [];
126
127
        if (is_object($data)) {
128
            foreach ($data ?? [] as $Column => $Value) {
129
                if (!is_array($Value) && !is_object($Value) && !empty($Column) && !is_numeric($Column)) {
130
                    $Columns[] = ['name' => $Column, 'type' => gettype($this->getActualDataType($Value, ""))];
131
                }
132
            }
133
        } elseif (is_array($data)) {
134
            $Columns[] = ['name' => 'value', 'type' => gettype($this->getActualDataType($data[0], ""))];
135
        }
136
137
        return $Columns;
138
    }
139
140
    /**
141
     * @param $data
142
     * @param $column
143
     * @return array
144
     */
145
    public function getData($data, $column)
146
    {
147
        $values = [];
148
149
        $index = 0;
150
        foreach ($data as $row_item) {
151
            foreach ($column as $column_item) {
152
                switch (is_object($row_item)) {
153
                    case true:
154
                        $values[$index][$column_item['name']] = $this->getActualDataType(($row_item->{$column_item['name']}) ?? null, null);
155
                        break;
156
                    case false:
157
                        $values[$index][$column_item['name']] = $this->getActualDataType(($data->{$column_item['name']}) ?? null, null);
158
                        break;
159
                }
160
            }
161
            $index++;
162
        }
163
164
165
        return $values;
166
    }
167
168
    /**
169
     * @param $input
170
     *
171
     * @return string
172
     */
173
    public static function snakeCase($input)
174
    {
175
        preg_match_all('!([A-Z][A-Z0-9]*(?=$|[A-Z][a-z0-9])|[A-Za-z][a-z0-9]+)!', $input, $matches);
176
        $ret = $matches[0];
177
178
        foreach ($ret as &$match) {
179
            $match = $match == strtoupper($match) ? strtolower($match) : lcfirst($match);
180
        }
181
182
        return implode('_', $ret);
183
    }
184
185
186
    /**
187
     * @param $array
188
     * @return bool|mixed
189
     */
190
    public static function getHighestColumnArray($array)
191
    {
192
        if (is_object($array) || (is_array($array) && !is_object($array[0]) && !is_array($array[0]))) {
193
            return $array;
194
        }
195
196
        $Highest = false;
197
        $ColumnCount = false;
198
        $HighestSubCount = false;
199
200
        foreach ($array as $array_item) {
201
            $current_sub = 0;
202
            //check how many array/object have
203
            foreach ($array_item as $SubTableName => $SubArrayItem) {
204
                if (is_array($SubArrayItem) || is_object($SubArrayItem)) {
205
                    $current_sub = $current_sub + 2;
206
                }
207
            }
208
            //check how many column have
209
            if ($ColumnCount <= count($array_item) || !$Highest) {
210
                if ($current_sub > $HighestSubCount || !$Highest) {
211
                    $Highest = $array_item;
212
                    $HighestSubCount = $current_sub;
213
                    $ColumnCount = count($array_item);
214
                }
215
            }
216
        }
217
218
219
        return $Highest;
220
    }
221
222
    /**
223
     * @param $array
224
     * @return string
225
     */
226
    public static function getStringFromData($array)
227
    {
228
        $String = [];
229
230
        foreach ($array as $item_row) {
231
            $value = [];
232
            foreach ($item_row as $item) {
233
                if (empty($item) && !is_numeric($item)) {
234
                    $value[] = "null";
235
                } elseif (is_numeric($item)) {
236
                    $value[] = $item;
237
                } else {
238
                    $value[] = '"' . addcslashes($item, "W") . '"';
239
                }
240
            }
241
            $String[] = '(' . implode(",", $value) . ')';
242
        }
243
244
        return "values" . implode(", ", $String);
245
    }
246
247
    /**
248
     * @param $array
249
     * @return string
250
     */
251
    public static function getStringFromColumns($array)
252
    {
253
        $String = [];
254
        foreach ($array as $column) {
255
            $String[] = "`" . JsonExtractor::snakeCase($column['name']) . "`";
256
        }
257
258
        return implode(",", $String);
259
    }
260
261
262
    /**
263
     * @param $Data
264
     * @param $empty_val
265
     * @return int|string
266
     */
267
    public static function getActualDataType($Data, $empty_val)
268
    {
269
        $Data = trim($Data);
270
        if (is_numeric($Data)) {
271
            return $Data + 0;
272
        } elseif (empty($Data)) {
273
            return $empty_val;
274
        } else {
275
            return (string)$Data;
276
        }
277
    }
278
}
279