Passed
Push — master ( 442876...4ec1bc )
by Felipe
15:55 queued 10:33
created

DataimportController::determineNull()   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 2
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
0 ignored issues
show
Coding Style introduced by
You must use "/**" style comments for a file comment
Loading history...
3
/*
4
 * PHPPgAdmin v6.0.0-beta.30
5
 */
6
7
namespace PHPPgAdmin\Controller;
8
9
/**
10
 * Base controller class.
11
 */
5 ignored issues
show
Coding Style introduced by
Missing @category tag in class comment
Loading history...
Coding Style introduced by
Missing @package tag in class comment
Loading history...
Coding Style introduced by
Missing @author tag in class comment
Loading history...
Coding Style introduced by
Missing @license tag in class comment
Loading history...
Coding Style introduced by
Missing @link tag in class comment
Loading history...
12
class DataimportController extends BaseController
13
{
14
    public $controller_name = 'DataimportController';
15
16
    /**
17
     * Default method to render the controller according to the action parameter.
18
     */
19
    public function render()
20
    {
21
        $misc   = $this->misc;
22
        $lang   = $this->lang;
23
        $action = $this->action;
0 ignored issues
show
Unused Code introduced by
The assignment to $action is dead and can be removed.
Loading history...
24
        $data   = $misc->getDatabaseAccessor();
25
26
        // Prevent timeouts on large exports
27
        set_time_limit(0);
28
29
        $this->printHeader($lang['strimport']);
30
        $this->printTrail('table');
31
        $this->printTabs('table', 'import');
32
33
        // Default state for XML parser
34
        $state         = 'XML';
35
        $curr_col_name = null;
36
        $curr_col_val  = null;
37
        $curr_col_null = false;
38
        $curr_row      = [];
0 ignored issues
show
Unused Code introduced by
The assignment to $curr_row is dead and can be removed.
Loading history...
39
40
        /**
41
         * Character data handler for XML import feature.
42
         *
43
         * @param $parser
44
         * @param $cdata
45
         */
46
        $_charHandler = function ($parser, $cdata) use (&$state, &$curr_col_val) {
47
            if ('COLUMN' == $state) {
48
                $curr_col_val .= $cdata;
49
            }
50
        };
51
52
        /**
53
         * Open tag handler for XML import feature.
54
         *
55
         * @param $parser
56
         * @param $name
57
         * @param $attrs
58
         */
59
        $_startElement = function ($parser, $name, $attrs) use ($data, $misc, &$state, &$curr_col_name, &$curr_col_null) {
0 ignored issues
show
Unused Code introduced by
The import $misc is not used and could be removed.

This check looks for imports that have been defined, but are not used in the scope.

Loading history...
60
            switch ($name) {
61
                case 'DATA':
62
                    if ('XML' != $state) {
63
                        $data->rollbackTransaction();
64
                        $this->printMsg($lang['strimporterror']);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $lang seems to be never defined.
Loading history...
65
                        exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
66
                    }
67
                    $state = 'DATA';
68
69
                    break;
70
                case 'HEADER':
71
                    if ('DATA' != $state) {
72
                        $data->rollbackTransaction();
73
                        $this->printMsg($lang['strimporterror']);
74
                        exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
75
                    }
76
                    $state = 'HEADER';
77
78
                    break;
79
                case 'RECORDS':
80
                    if ('READ_HEADER' != $state) {
81
                        $data->rollbackTransaction();
82
                        $this->printMsg($lang['strimporterror']);
83
                        exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
84
                    }
85
                    $state = 'RECORDS';
86
87
                    break;
88
                case 'ROW':
89
                    if ('RECORDS' != $state) {
90
                        $data->rollbackTransaction();
91
                        $this->printMsg($lang['strimporterror']);
92
                        exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
93
                    }
94
                    $state    = 'ROW';
95
                    $curr_row = [];
1 ignored issue
show
Unused Code introduced by
The assignment to $curr_row is dead and can be removed.
Loading history...
96
97
                    break;
98
                case 'COLUMN':
99
                    // We handle columns in rows
100
                    if ('ROW' == $state) {
101
                        $state         = 'COLUMN';
102
                        $curr_col_name = $attrs['NAME'];
103
                        $curr_col_null = isset($attrs['NULL']);
104
                    }
105
                    // And we ignore columns in headers and fail in any other context
106
                    elseif ('HEADER' != $state) {
0 ignored issues
show
Coding Style introduced by
Expected "} elseif (...) \n"; found "\n // And we ignore columns in headers and fail in any other context\n elseif (...) {\n"
Loading history...
107
                        $data->rollbackTransaction();
108
                        $this->printMsg($lang['strimporterror']);
109
                        exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
110
                    }
111
112
                    break;
113
                default:
114
                    // An unrecognised tag means failure
115
                    $data->rollbackTransaction();
116
                    $this->printMsg($lang['strimporterror']);
117
                    exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
118
            }
119
        };
120
121
        /**
122
         * Close tag handler for XML import feature.
123
         *
124
         * @param $parser
125
         * @param $name
126
         */
127
        $_endElement = function ($parser, $name) use ($data, $misc, &$state, &$curr_col_name, &$curr_col_null, &$curr_col_val) {
0 ignored issues
show
Unused Code introduced by
The import $misc is not used and could be removed.

This check looks for imports that have been defined, but are not used in the scope.

Loading history...
128
            switch ($name) {
129
                case 'DATA':
130
                    $state = 'READ_DATA';
131
132
                    break;
133
                case 'HEADER':
134
                    $state = 'READ_HEADER';
135
136
                    break;
137
                case 'RECORDS':
138
                    $state = 'READ_RECORDS';
139
140
                    break;
141
                case 'ROW':
142
                    // Build value map in order to insert row into table
143
                    $fields = [];
144
                    $vars   = [];
145
                    $nulls  = [];
146
                    $format = [];
147
                    $types  = [];
148
                    $i      = 0;
149
                    foreach ($curr_row as $k => $v) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $curr_row seems to be never defined.
Loading history...
150
                        $fields[$i] = $k;
151
                        // Check for nulls
152
                        if (null === $v) {
153
                            $nulls[$i] = 'on';
154
                        }
155
156
                        // Add to value array
157
                        $vars[$i] = $v;
158
                        // Format is always VALUE
159
                        $format[$i] = 'VALUE';
160
                        // Type is always text
161
                        $types[$i] = 'text';
162
                        ++$i;
163
                    }
164
                    $status = $data->insertRow($_REQUEST['table'], $fields, $vars, $nulls, $format, $types);
165
                    if (0 != $status) {
166
                        $data->rollbackTransaction();
167
                        $this->printMsg($lang['strimporterror']);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $lang seems to be never defined.
Loading history...
168
                        exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
169
                    }
170
                    $curr_row = [];
0 ignored issues
show
Unused Code introduced by
The assignment to $curr_row is dead and can be removed.
Loading history...
171
                    $state    = 'RECORDS';
172
173
                    break;
174
                case 'COLUMN':
175
                    $curr_row[$curr_col_name] = ($curr_col_null ? null : $curr_col_val);
0 ignored issues
show
Comprehensibility Best Practice introduced by
$curr_row was never initialized. Although not strictly required by PHP, it is generally a good practice to add $curr_row = array(); before regardless.
Loading history...
176
                    $curr_col_name            = null;
177
                    $curr_col_val             = null;
178
                    $curr_col_null            = false;
179
                    $state                    = 'ROW';
180
181
                    break;
182
                default:
183
                    // An unrecognised tag means failure
184
                    $data->rollbackTransaction();
185
                    $this->printMsg($lang['strimporterror']);
186
                    exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
187
            }
188
        };
189
190
        // Check that file is specified and is an uploaded file
191
        if (isset($_FILES['source']) && is_uploaded_file($_FILES['source']['tmp_name']) && is_readable($_FILES['source']['tmp_name'])) {
192
            $fd = fopen($_FILES['source']['tmp_name'], 'rb');
193
            // Check that file was opened successfully
194
            if (false !== $fd) {
195
                $null_array = self::loadNULLArray();
196
                $status     = $data->beginTransaction();
197
                if (0 != $status) {
198
                    $this->printMsg($lang['strimporterror']);
199
                    exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
200
                }
201
202
                // If format is set to 'auto', then determine format automatically from file name
203
                if ('auto' == $_REQUEST['format']) {
204
                    $extension = substr(strrchr($_FILES['source']['name'], '.'), 1);
205
                    switch ($extension) {
206
                        case 'csv':
207
                            $_REQUEST['format'] = 'csv';
208
209
                            break;
210
                        case 'txt':
211
                            $_REQUEST['format'] = 'tab';
212
213
                            break;
214
                        case 'xml':
215
                            $_REQUEST['format'] = 'xml';
216
217
                            break;
218
                        default:
219
                            $data->rollbackTransaction();
220
                            $this->printMsg($lang['strimporterror-fileformat']);
221
                            exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
222
                    }
223
                }
224
225
                // Do different import technique depending on file format
226
                switch ($_REQUEST['format']) {
227
                    case 'csv':
228
                    case 'tab':
229
                        // XXX: Length of CSV lines limited to 100k
230
                        $csv_max_line = 100000;
231
                        // Set delimiter to tabs or commas
232
                        if ('csv' == $_REQUEST['format']) {
233
                            $csv_delimiter = ',';
234
                        } else {
235
                            $csv_delimiter = "\t";
236
                        }
237
238
                        // Get first line of field names
239
                        $fields = fgetcsv($fd, $csv_max_line, $csv_delimiter);
240
                        $row    = 2; //We start on the line AFTER the field names
241
                        while ($line = fgetcsv($fd, $csv_max_line, $csv_delimiter)) {
242
                            // Build value map
243
                            $t_fields = [];
244
                            $vars     = [];
245
                            $nulls    = [];
246
                            $format   = [];
247
                            $types    = [];
248
                            $i        = 0;
249
                            foreach ($fields as $f) {
250
                                // Check that there is a column
251
                                if (!isset($line[$i])) {
252
                                    $this->printMsg(sprintf($lang['strimporterrorline-badcolumnnum'], $row));
253
                                    exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
254
                                }
255
                                $t_fields[$i] = $f;
256
257
                                // Check for nulls
258
                                if (self::determineNull($line[$i], $null_array)) {
259
                                    $nulls[$i] = 'on';
260
                                }
261
                                // Add to value array
262
                                $vars[$i] = $line[$i];
263
                                // Format is always VALUE
264
                                $format[$i] = 'VALUE';
265
                                // Type is always text
266
                                $types[$i] = 'text';
267
                                ++$i;
268
                            }
269
270
                            $status = $data->insertRow($_REQUEST['table'], $t_fields, $vars, $nulls, $format, $types);
271
                            if (0 != $status) {
272
                                $data->rollbackTransaction();
273
                                $this->printMsg(sprintf($lang['strimporterrorline'], $row));
274
                                exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
275
                            }
276
                            ++$row;
277
                        }
278
279
                        break;
280
                    case 'xml':
281
                        $parser = xml_parser_create();
282
                        xml_set_element_handler($parser, $_startElement, $_endElement);
283
                        xml_set_character_data_handler($parser, $_charHandler);
284
285
                        while (!feof($fd)) {
286
                            $line = fgets($fd, 4096);
287
                            xml_parse($parser, $line);
288
                        }
289
290
                        xml_parser_free($parser);
291
292
                        break;
293
                    default:
294
                        // Unknown type
295
                        $data->rollbackTransaction();
296
                        $this->printMsg($lang['strinvalidparam']);
297
                        exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
298
                }
299
300
                $status = $data->endTransaction();
301
                if (0 != $status) {
302
                    $this->printMsg($lang['strimporterror']);
303
                    exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
304
                }
305
                fclose($fd);
306
307
                $this->printMsg($lang['strfileimported']);
308
            } else {
309
                // File could not be opened
310
                $this->printMsg($lang['strimporterror']);
311
            }
312
        } else {
313
            // Upload went wrong
314
            $this->printMsg($lang['strimporterror-uploadedfile']);
315
        }
316
317
        $this->printFooter();
318
    }
319
320
    public static function loadNULLArray()
1 ignored issue
show
Coding Style introduced by
Missing function doc comment
Loading history...
321
    {
322
        $array = [];
323
        if (isset($_POST['allowednulls'])) {
324
            foreach ($_POST['allowednulls'] as $null_char) {
325
                $array[] = $null_char;
326
            }
327
        }
328
329
        return $array;
330
    }
331
332
    public static function determineNull($field, $null_array)
1 ignored issue
show
Coding Style introduced by
Missing function doc comment
Loading history...
333
    {
334
        return in_array($field, $null_array, true);
335
    }
336
}
337