Passed
Push — develop ( c2019a...2cab77 )
by Felipe
04:50
created

DataexportController   F

Complexity

Total Complexity 82

Size/Duplication

Total Lines 465
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 82
dl 0
loc 465
rs 1.5789
c 0
b 0
f 0

9 Methods

Rating   Name   Duplication   Size   Complexity  
C render() 0 65 13
C _csvOrTab() 0 48 13
C _mimicCopy() 0 29 7
B pickFormat() 0 19 5
D mimicDumpFeature() 0 105 12
C _mimicSQL() 0 40 8
C _mimicXml() 0 34 7
D _mimicHtml() 0 41 9
C doDefault() 0 52 8

How to fix   Complexity   

Complex Class

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

1
<?php
2
3
/**
4
 * PHPPgAdmin v6.0.0-beta.48
5
 */
6
7
namespace PHPPgAdmin\Controller;
8
9
/**
10
 * Base controller class.
11
 *
12
 * @package PHPPgAdmin
13
 */
14
class DataexportController extends BaseController
15
{
16
    public $extensions = [
17
        'sql'  => 'sql',
18
        'copy' => 'sql',
19
        'csv'  => 'csv',
20
        'tab'  => 'txt',
21
        'html' => 'html',
22
        'xml'  => 'xml',
23
    ];
24
    public $controller_title = 'strexport';
25
26
    /**
27
     * Default method to render the controller according to the action parameter.
28
     */
29
    public function render()
30
    {
31
        set_time_limit(0);
32
33
        // if (!isset($_REQUEST['table']) && !isset($_REQUEST['query']))
34
        // What must we do in this case? Maybe redirect to the homepage?
35
36
        $format = 'N/A';
37
38
        // force behavior to assume there is no pg_dump in the system
39
        $forcemimic = false;
40
41
        // If format is set, then perform the export
42
        if (!isset($_REQUEST['what'])) {
43
            return $this->doDefault();
44
        }
45
46
        $this->prtrace("REQUEST['what']", $_REQUEST['what']);
47
48
        // Include application functions
49
        $this->setNoOutput(true);
50
        $clean = false;
51
        $oids  = false;
52
        switch ($_REQUEST['what']) {
53
            case 'dataonly':
54
                // Check to see if they have pg_dump set up and if they do, use that
55
                // instead of custom dump code
56
                if (!$forcemimic && $this->misc->isDumpEnabled() && ('copy' == $_REQUEST['d_format'] || 'sql' == $_REQUEST['d_format'])) {
57
                    $this->prtrace('DUMP ENABLED, d_format is', $_REQUEST['d_format']);
58
                    $dbexport_controller = new \PHPPgAdmin\Controller\DbexportController($this->getContainer());
59
60
                    return $dbexport_controller->render();
61
                }
62
                $this->prtrace('d_format is', $_REQUEST['d_format'], 'd_oids is', isset($_REQUEST['d_oids']));
63
                $format = $_REQUEST['d_format'];
64
                $oids   = isset($_REQUEST['d_oids']);
65
66
                break;
67
            case 'structureonly':
68
                // Check to see if they have pg_dump set up and if they do, use that
69
                // instead of custom dump code
70
                if (!$forcemimic && $this->misc->isDumpEnabled()) {
71
                    $dbexport_controller = new \PHPPgAdmin\Controller\DbexportController($this->getContainer());
72
73
                    return $dbexport_controller->render();
74
                }
75
                $clean = isset($_REQUEST['s_clean']);
76
77
                break;
78
            case 'structureanddata':
79
                // Check to see if they have pg_dump set up and if they do, use that
80
                // instead of custom dump code
81
                if (!$forcemimic && $this->misc->isDumpEnabled()) {
82
                    $dbexport_controller = new \PHPPgAdmin\Controller\DbexportController($this->getContainer());
83
84
                    return $dbexport_controller->render();
85
                }
86
                $format = $_REQUEST['sd_format'];
87
                $clean  = isset($_REQUEST['sd_clean']);
88
                $oids   = isset($_REQUEST['sd_oids']);
89
90
                break;
91
        }
92
93
        return $this->mimicDumpFeature($format, $clean, $oids);
94
    }
95
96
    protected function mimicDumpFeature($format, $clean, $oids)
97
    {
98
        $data = $this->misc->getDatabaseAccessor();
99
100
        set_time_limit(0);
101
102
        // if (!isset($_REQUEST['table']) && !isset($_REQUEST['query']))
103
        // What must we do in this case? Maybe redirect to the homepage?
104
105
        // If format is set, then perform the export
106
        if (!isset($_REQUEST['what'])) {
107
            return $this->doDefault();
108
        }
109
110
        $this->prtrace("REQUEST['what']", $_REQUEST['what']);
111
112
        // Include application functions
113
        $this->setNoOutput(true);
114
        $clean    = false;
115
        $response = $this
116
            ->container
117
            ->responseobj;
118
119
        // Make it do a download, if necessary
120
        if ('download' == $_REQUEST['output']) {
121
            // Set headers.  MSIE is totally broken for SSL downloading, so
122
            // we need to have it download in-place as plain text
123
            if (strstr($_SERVER['HTTP_USER_AGENT'], 'MSIE') && isset($_SERVER['HTTPS'])) {
124
                $response = $response
125
                    ->withHeader('Content-type', 'text/plain');
126
            } else {
127
                $response = $response
128
                    ->withHeader('Content-type', 'application/download');
129
130
                if (isset($this->extensions[$format])) {
131
                    $ext = $this->extensions[$format];
132
                } else {
133
                    $ext = 'txt';
134
                }
135
                $response = $response
136
                    ->withHeader('Content-Disposition', 'attachment; filename=dump.'.$ext);
137
            }
138
        } else {
139
            $response = $response
140
                ->withHeader('Content-type', 'text/plain');
141
        }
142
143
        $this->coalesceArr($_REQUEST, 'query', '');
144
145
        $_REQUEST['query'] = trim(urldecode($_REQUEST['query']));
146
147
        // Set the schema search path
148
        if (isset($_REQUEST['search_path'])) {
149
            $data->setSearchPath(array_map('trim', explode(',', $_REQUEST['search_path'])));
150
        } elseif (isset($_REQUEST['schema'])) {
151
            $data->setSearchPath($_REQUEST['schema']);
152
        }
153
154
        $subject = $this->coalesceArr($_REQUEST, 'subject', 'table')['subject'];
155
156
        $object = $this->coalesceArr($_REQUEST, $subject)[$subject];
157
158
        // Set up the dump transaction
159
        $status = $data->beginDump();
160
        $this->prtrace('subject', $subject);
161
        $this->prtrace('object', $object);
162
        $tabledefprefix = '';
163
        $tabledefsuffix = '';
164
165
        // If the dump is not dataonly then dump the structure prefix
166
        if ('dataonly' != $_REQUEST['what']) {
167
            $tabledefprefix = $data->getTableDefPrefix($object, $clean);
168
            $this->prtrace('tabledefprefix', $tabledefprefix);
169
            echo $tabledefprefix;
170
        }
171
172
        // If the dump is not structureonly then dump the actual data
173
        if ('structureonly' != $_REQUEST['what']) {
174
            // Get database encoding
175
            //$dbEncoding = $data->getDatabaseEncoding();
176
177
            // Set fetch mode to NUM so that duplicate field names are properly returned
178
            $data->conn->setFetchMode(\ADODB_FETCH_NUM);
179
180
            // Execute the query, if set, otherwise grab all rows from the table
181
            if ($object) {
182
                $rs = $data->dumpRelation($object, $oids);
183
            } else {
184
                $rs = $data->conn->Execute($_REQUEST['query']);
185
                $this->prtrace('$_REQUEST[query]', $_REQUEST['query']);
186
            }
187
188
            $response = $this->pickFormat($data, $object, $oids, $rs, $format, $response);
189
        }
190
        if ('dataonly' != $_REQUEST['what']) {
191
            $data->conn->setFetchMode(\ADODB_FETCH_ASSOC);
192
            $tabledefsuffix = $data->getTableDefSuffix($object);
193
            $this->prtrace('tabledefsuffix', $tabledefsuffix);
194
            echo $tabledefsuffix;
195
        }
196
197
        // Finish the dump transaction
198
        $status = $data->endDump();
199
200
        return $response;
201
    }
202
203
    public function pickFormat($data, $object, $oids, $rs, $format, $response)
204
    {
205
        if ('copy' == $format) {
206
            $this->_mimicCopy($data, $object, $oids, $rs);
207
        } elseif ('html' == $format) {
208
            $response = $response
209
                ->withHeader('Content-type', 'text/html');
210
            $this->_mimicHtml($data, $object, $oids, $rs);
211
        } elseif ('xml' == $format) {
212
            $response = $response
213
                ->withHeader('Content-type', 'application/xml');
214
            $this->_mimicXml($data, $object, $oids, $rs);
215
        } elseif ('sql' == $format) {
216
            $this->_mimicSQL($data, $object, $oids, $rs);
217
        } else {
218
            $this->_csvOrTab($data, $object, $oids, $rs, $format);
219
        }
220
221
        return $response;
222
    }
223
224
    public function doDefault($msg = '')
225
    {
226
        if (!isset($_REQUEST['query']) || empty($_REQUEST['query'])) {
227
            $_REQUEST['query'] = $_SESSION['sqlquery'];
228
        }
229
230
        $this->printHeader();
231
        $this->printBody();
232
        $this->printTrail(isset($_REQUEST['subject']) ? $_REQUEST['subject'] : 'database');
233
        $this->printTitle($this->lang['strexport']);
234
        if (isset($msg)) {
235
            $this->printMsg($msg);
236
        }
237
238
        echo '<form action="'.\SUBFOLDER.'/src/views/dataexport" method="post">'.PHP_EOL;
239
        echo '<table>'.PHP_EOL;
240
        echo "<tr><th class=\"data\">{$this->lang['strformat']}:</th><td><select name=\"d_format\">".PHP_EOL;
241
        // COPY and SQL require a table
242
        if (isset($_REQUEST['table'])) {
243
            echo '<option value="copy">COPY</option>'.PHP_EOL;
244
            echo '<option value="sql">SQL</option>'.PHP_EOL;
245
        }
246
        echo '<option value="csv">CSV</option>'.PHP_EOL;
247
        echo "<option value=\"tab\">{$this->lang['strtabbed']}</option>".PHP_EOL;
248
        echo '<option value="html">XHTML</option>'.PHP_EOL;
249
        echo '<option value="xml">XML</option>'.PHP_EOL;
250
        echo '</select></td></tr>';
251
        echo '</table>'.PHP_EOL;
252
253
        echo "<h3>{$this->lang['stroptions']}</h3>".PHP_EOL;
254
        echo "<p><input type=\"radio\" id=\"output1\" name=\"output\" value=\"show\" checked=\"checked\" /><label for=\"output1\">{$this->lang['strshow']}</label>".PHP_EOL;
255
        echo "<br/><input type=\"radio\" id=\"output2\" name=\"output\" value=\"download\" /><label for=\"output2\">{$this->lang['strdownload']}</label></p>".PHP_EOL;
256
257
        echo '<p><input type="hidden" name="action" value="export" />'.PHP_EOL;
258
        echo '<input type="hidden" name="what" value="dataonly" />'.PHP_EOL;
259
        if (isset($_REQUEST['table'])) {
260
            echo '<input type="hidden" name="subject" value="table" />'.PHP_EOL;
261
            echo '<input type="hidden" name="table" value="', htmlspecialchars($_REQUEST['table']), '" />'.PHP_EOL;
262
        } else {
263
            echo '<input type="hidden" name="subject" value="table" />'.PHP_EOL;
264
        }
265
        $this->prtrace('$_REQUEST[query]', $_REQUEST['query'], htmlspecialchars(urlencode($_REQUEST['query'])));
266
        $this->prtrace('$_SESSION[sqlquery]', $_SESSION['sqlquery'], htmlspecialchars(urlencode($_SESSION['sqlquery'])));
267
        echo '<input type="hidden" name="query" value="', htmlspecialchars(urlencode($_REQUEST['query'])), '" />'.PHP_EOL;
268
        if (isset($_REQUEST['search_path'])) {
269
            echo '<input type="hidden" name="search_path" value="', htmlspecialchars($_REQUEST['search_path']), '" />'.PHP_EOL;
270
        }
271
        echo $this->misc->form;
272
        echo "<input type=\"submit\" value=\"{$this->lang['strexport']}\" /></p>".PHP_EOL;
273
        echo '</form>'.PHP_EOL;
274
275
        $this->printFooter();
276
    }
277
278
    private function _mimicCopy($data, $object, $oids, $rs)
279
    {
280
        $data->fieldClean($object);
281
        echo "COPY \"{$_REQUEST['table']}\"";
282
        if ($oids) {
283
            echo ' WITH OIDS';
284
        }
285
286
        echo " FROM stdin;\n";
287
        while (!$rs->EOF) {
288
            $first = true;
289
            //while (list($k, $v) = each($rs->fields)) {
290
            foreach ($rs->fields as $k => $v) {
291
                // Escape value
292
                $v = $data->escapeBytea($v);
293
294
                // We add an extra escaping slash onto octal encoded characters
295
                $v = preg_replace('/\\\\([0-7]{3})/', '\\\\\1', $v);
296
                if ($first) {
297
                    echo (is_null($v)) ? '\\N' : $v;
298
                    $first = false;
299
                } else {
300
                    echo "\t", (is_null($v)) ? '\\N' : $v;
301
                }
302
            }
303
            echo PHP_EOL;
304
            $rs->moveNext();
305
        }
306
        echo "\\.\n";
307
    }
308
309
    private function _mimicHtml($data, $object, $oids, $rs)
310
    {
311
        echo "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\r\n";
312
        echo "<html xmlns=\"http://www.w3.org/1999/xhtml\">\r\n";
313
        echo "<head>\r\n";
314
        echo "\t<title></title>\r\n";
315
        echo "\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\r\n";
316
        echo "</head>\r\n";
317
        echo "<body>\r\n";
318
        echo "<table class=\"phppgadmin\">\r\n";
319
        echo "\t<tr>\r\n";
320
        if (!$rs->EOF) {
321
            // Output header row
322
            $j = 0;
323
            foreach ($rs->fields as $k => $v) {
324
                $finfo = $rs->fetchField($j++);
325
                if ($finfo->name == $data->id && !$oids) {
326
                    continue;
327
                }
328
329
                echo "\t\t<th>", $this->misc->printVal($finfo->name, 'verbatim'), "</th>\r\n";
330
            }
331
        }
332
        echo "\t</tr>\r\n";
333
        while (!$rs->EOF) {
334
            echo "\t<tr>\r\n";
335
            $j = 0;
336
            foreach ($rs->fields as $k => $v) {
337
                $finfo = $rs->fetchField($j++);
338
                if ($finfo->name == $data->id && !$oids) {
339
                    continue;
340
                }
341
342
                echo "\t\t<td>", $this->misc->printVal($v, 'verbatim', $finfo->type), "</td>\r\n";
343
            }
344
            echo "\t</tr>\r\n";
345
            $rs->moveNext();
346
        }
347
        echo "</table>\r\n";
348
        echo "</body>\r\n";
349
        echo "</html>\r\n";
350
    }
351
352
    private function _mimicXml($data, $object, $oids, $rs)
353
    {
354
        echo '<?xml version="1.0" encoding="utf-8" ?>'.PHP_EOL;
355
        echo '<data>'.PHP_EOL;
356
        if (!$rs->EOF) {
357
            // Output header row
358
            $j = 0;
359
            echo "\t<header>".PHP_EOL;
360
            foreach ($rs->fields as $k => $v) {
361
                $finfo = $rs->fetchField($j++);
362
                $name  = htmlspecialchars($finfo->name);
363
                $type  = htmlspecialchars($finfo->type);
364
                echo "\t\t<column name=\"{$name}\" type=\"{$type}\" />".PHP_EOL;
365
            }
366
            echo "\t</header>".PHP_EOL;
367
        }
368
        echo "\t<records>".PHP_EOL;
369
        while (!$rs->EOF) {
370
            $j = 0;
371
            echo "\t\t<row>".PHP_EOL;
372
            foreach ($rs->fields as $k => $v) {
373
                $finfo = $rs->fetchField($j++);
374
                $name  = htmlspecialchars($finfo->name);
375
                if (!is_null($v)) {
376
                    $v = htmlspecialchars($v);
377
                }
378
379
                echo "\t\t\t<column name=\"{$name}\"", (is_null($v) ? ' null="null"' : ''), ">{$v}</column>".PHP_EOL;
380
            }
381
            echo "\t\t</row>".PHP_EOL;
382
            $rs->moveNext();
383
        }
384
        echo "\t</records>".PHP_EOL;
385
        echo '</data>'.PHP_EOL;
386
    }
387
388
    private function _mimicSQL($data, $object, $oids, $rs)
389
    {
390
        $data->fieldClean($object);
391
        $values = '';
392
        while (!$rs->EOF) {
393
            echo "INSERT INTO \"{$object}\" (";
394
            $first = true;
395
            $j     = 0;
396
            foreach ($rs->fields as $k => $v) {
397
                $finfo = $rs->fetchField($j++);
398
                $k     = $finfo->name;
399
                // SQL (INSERT) format cannot handle oids
400
                //                        if ($k == $data->id) continue;
401
                // Output field
402
                $data->fieldClean($k);
403
                if ($first) {
404
                    echo "\"{$k}\"";
405
                } else {
406
                    echo ", \"{$k}\"";
407
                }
408
409
                if (!is_null($v)) {
410
                    // Output value
411
                    // addCSlashes converts all weird ASCII characters to octal representation,
412
                    // EXCEPT the 'special' ones like \r \n \t, etc.
413
                    $v = addcslashes($v, "\0..\37\177..\377");
414
                    // We add an extra escaping slash onto octal encoded characters
415
                    $v = preg_replace('/\\\\([0-7]{3})/', '\\\1', $v);
416
                    // Finally, escape all apostrophes
417
                    $v = str_replace("'", "''", $v);
418
                }
419
                if ($first) {
420
                    $values = (is_null($v) ? 'NULL' : "'{$v}'");
421
                    $first  = false;
422
                } else {
423
                    $values .= ', '.((is_null($v) ? 'NULL' : "'{$v}'"));
424
                }
425
            }
426
            echo ") VALUES ({$values});\n";
427
            $rs->moveNext();
428
        }
429
    }
430
431
    private function _csvOrTab($data, $object, $oids, $rs, $format)
432
    {
433
        switch ($format) {
434
            case 'tab':
435
                $sep = "\t";
436
437
                break;
438
            case 'csv':
439
            default:
440
                $sep = ',';
441
442
                break;
443
        }
444
        if (!$rs->EOF) {
445
            // Output header row
446
            $first = true;
447
            foreach ($rs->fields as $k => $v) {
448
                $finfo = $rs->fetchField($k);
449
                $v     = $finfo->name;
450
                if (!is_null($v)) {
451
                    $v = str_replace('"', '""', $v);
452
                }
453
454
                if ($first) {
455
                    echo "\"{$v}\"";
456
                    $first = false;
457
                } else {
458
                    echo "{$sep}\"{$v}\"";
459
                }
460
            }
461
            echo "\r\n";
462
        }
463
        while (!$rs->EOF) {
464
            $first = true;
465
            foreach ($rs->fields as $k => $v) {
466
                if (!is_null($v)) {
467
                    $v = str_replace('"', '""', $v);
468
                }
469
470
                if ($first) {
471
                    echo (is_null($v)) ? '"\\N"' : "\"{$v}\"";
472
                    $first = false;
473
                } else {
474
                    echo is_null($v) ? "{$sep}\"\\N\"" : "{$sep}\"{$v}\"";
475
                }
476
            }
477
            echo "\r\n";
478
            $rs->moveNext();
479
        }
480
    }
481
}
482