Completed
Push — master ( 03c10c...407786 )
by Supun
10s
created

JsonExtractor::getTablesArray()   A

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
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
73
            } elseif (is_array($value) || is_object($value)) {//if it's a array and  firs element is not a object
74
75
                $table_data = $this->getTable($prefix . $table_name, $value);
76
                $this->table[$table_data['tables']['name']] = $table_data['tables']['column'];
77
                $this->data[$table_data['data']['table']] = $table_data['data']['data'];
78
            }
79
        }
80
81
    }
82
83
84
    /**
85
     * @param $table
86
     * @param $data
87
     * @return array
88
     */
89
    public function getTable($table, $data)
90
    {
91
        $column = $this->getColumn($this->getHighestColumnArray($data));
92
93
94
        if ($this->snake_case_table)
95
            $table = $this->snakeCase($table);
96
97
        $table_data = $this->getData($data, $column);
98
99
        $last_columns = $column;
100
        if ($this->need_id && array_search('id', array_column($column, 'name')) === false) {
101
102
            $last_columns[] = [
103
                'name' => "id",
104
                'type' => "int"
105
            ];
106
        }
107
108
        return [
109
            'tables' => [
110
                'name' => $table,
111
                'column' => $last_columns
112
            ],
113
            'data' => [
114
                'table' => $table,
115
                'data' => $table_data
116
            ]
117
        ];
118
    }
119
120
    /**
121
     * @param $data
122
     *
123
     * @return array
124
     */
125
    public function getColumn($data)
126
    {
127
        $Columns = [];
128
129
        if (is_object($data)) {
130
            foreach ($data ?? [] as $Column => $Value) {
131
                if (!is_array($Value) && !is_object($Value) && !empty($Column) && !is_numeric($Column)) {
132
                    $Columns[] = ['name' => $Column, 'type' => gettype($this->getActualDataType($Value, ""))];
133
                }
134
            }
135
        } elseif (is_array($data)) {
136
            $Columns[] = ['name' => 'value', 'type' => gettype($this->getActualDataType($data[0], ""))];
137
        }
138
139
        return $Columns;
140
    }
141
142
    /**
143
     * @param $data
144
     * @param $column
145
     * @return array
146
     */
147
    function getData($data, $column)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
148
    {
149
        $values = [];
150
151
        $index = 0;
152
        foreach ($data as $row_item) {
153
            foreach ($column as $column_item) {
154
                switch (is_object($row_item)) {
155
                    case true:
156
                        $values[$index][$column_item['name']] = $this->getActualDataType(($row_item->{$column_item['name']}) ?? null, null);
157
                        break;
158
                    case false:
159
                        $values[$index][$column_item['name']] = $this->getActualDataType(($data->{$column_item['name']}) ?? null, null);
160
                        break;
161
                }
162
163
            }
164
            $index++;
165
        }
166
167
168
        return $values;
169
170
    }
171
172
    /**
173
     * @param $input
174
     *
175
     * @return string
176
     */
177
    public static function snakeCase($input)
178
    {
179
        preg_match_all('!([A-Z][A-Z0-9]*(?=$|[A-Z][a-z0-9])|[A-Za-z][a-z0-9]+)!', $input, $matches);
180
        $ret = $matches[0];
181
182
        foreach ($ret as &$match) {
183
            $match = $match == strtoupper($match) ? strtolower($match) : lcfirst($match);
184
        }
185
186
        return implode('_', $ret);
187
    }
188
189
190
    /**
191
     * @param $array
192
     * @return bool|mixed
193
     */
194
    public static function getHighestColumnArray($array)
195
    {
196
        if (is_object($array) || (is_array($array) && !is_object($array[0]) && !is_array($array[0])))
197
            return $array;
198
199
        $Highest = false;
200
        $ColumnCount = false;
201
        $HighestSubCount = false;
202
203
        foreach ($array as $array_item) {
204
205
            $current_sub = 0;
206
            //check how many array/object have
207
            foreach ($array_item as $SubTableName => $SubArrayItem) {
208
                if (is_array($SubArrayItem) || is_object($SubArrayItem)) {
209
                    $current_sub = $current_sub + 2;
210
                }
211
212
            }
213
            //check how many column have
214
            if ($ColumnCount <= count($array_item) || !$Highest) {
215
                if ($current_sub > $HighestSubCount || !$Highest) {
216
                    $Highest = $array_item;
217
                    $HighestSubCount = $current_sub;
218
                    $ColumnCount = count($array_item);
219
                }
220
            }
221
        }
222
223
224
        return $Highest;
225
    }
226
227
    /**
228
     * @param $array
229
     * @return string
230
     */
231
    public static function getStringFromData($array)
232
    {
233
        $String = [];
234
235
        foreach ($array as $item_row) {
236
            $value = [];
237
            foreach ($item_row as $item) {
238
                if (empty($item) && !is_numeric($item)) {
239
                    $value[] = "null";
240
                } elseif (is_numeric($item))
241
                    $value[] = $item;
242
                else
243
                    $value[] = '"' . addcslashes($item, "W") . '"';
244
            }
245
            $String[] = '(' . implode(",", $value) . ')';
246
        }
247
248
        return "values" . implode(", ", $String);
249
    }
250
251
    /**
252
     * @param $array
253
     * @return string
254
     */
255
    public static function getStringFromColumns($array)
256
    {
257
        $String = [];
258
        foreach ($array as $column) {
259
            $String[] = "`" . JsonExtractor::snakeCase($column['name']) . "`";
260
        }
261
262
        return implode(",", $String);
263
    }
264
265
    /**
266
     * @param $Data
267
     * @param null $empty_val
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $empty_val is correct as it would always require null to be passed?
Loading history...
268
     * @return int|null|string
269
     */
270
    public static function getActualDataType($Data, $empty_val = null)
271
    {
272
        $Data = trim($Data);
273
        if (is_numeric($Data)) {
274
            return $Data + 0;
275
        } elseif (empty($Data))
276
            return $empty_val;
277
        else
278
            return (string)$Data;
279
    }
280
}
281