Test Failed
Branch develop (db5506)
by Felipe
03:46
created

DataexportController   F

Complexity

Total Complexity 71

Size/Duplication

Total Lines 379
Duplicated Lines 8.18 %

Importance

Changes 0
Metric Value
dl 31
loc 379
rs 2.6315
c 0
b 0
f 0
wmc 71

2 Methods

Rating   Name   Duplication   Size   Complexity  
F render() 31 311 63
B doDefault() 0 53 8

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

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
namespace PHPPgAdmin\Controller;
4
5
/**
6
 * Base controller class
7
 */
8
class DataexportController extends BaseController
9
{
10
    public $_name      = 'DataexportController';
11
    public $extensions = [
12
        'sql'  => 'sql',
13
        'copy' => 'sql',
14
        'csv'  => 'csv',
15
        'tab'  => 'txt',
16
        'html' => 'html',
17
        'xml'  => 'xml',
18
    ];
19
20
    public function render()
0 ignored issues
show
Coding Style introduced by
render uses the super-global variable $_REQUEST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
Coding Style introduced by
render uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
21
    {
22
        $conf   = $this->conf;
23
        $misc   = $this->misc;
24
        $lang   = $this->lang;
25
        $data   = $misc->getDatabaseAccessor();
26
        $action = $this->action;
27
28
        set_time_limit(0);
29
30
        // if (!isset($_REQUEST['table']) && !isset($_REQUEST['query']))
31
        // What must we do in this case? Maybe redirect to the homepage?
32
33
        // If format is set, then perform the export
34
        if (isset($_REQUEST['what'])) {
35
            $this->prtrace("REQUEST['what']", $_REQUEST['what']);
36
37
            // Include application functions
38
            $this->setNoOutput(true);
39
40
            switch ($_REQUEST['what']) {
41
                case 'dataonly':
42
                    // Check to see if they have pg_dump set up and if they do, use that
43
                    // instead of custom dump code
44
                    if ($misc->isDumpEnabled() && ($_REQUEST['d_format'] == 'copy' || $_REQUEST['d_format'] == 'sql')) {
45
                        $this->prtrace('DUMP ENABLED, d_format is', $_REQUEST['d_format']);
46
                        $dbexport_controller = new \PHPPgAdmin\Controller\DbexportController($this->getContainer());
47
                        return $dbexport_controller->render();
48
                    } else {
49
                        $this->prtrace('d_format is', $_REQUEST['d_format'], 'd_oids is', isset($_REQUEST['d_oids']));
50
                        $format = $_REQUEST['d_format'];
51
                        $oids   = isset($_REQUEST['d_oids']);
52
                    }
53
                    break;
54
                case 'structureonly':
55
                    // Check to see if they have pg_dump set up and if they do, use that
56
                    // instead of custom dump code
57
                    if ($misc->isDumpEnabled()) {
58
                        $dbexport_controller = new \PHPPgAdmin\Controller\DbexportController($this->getContainer());
59
                        return $dbexport_controller->render();
60
                    } else {
61
                        $clean = isset($_REQUEST['s_clean']);
62
                    }
63
64
                    break;
65
                case 'structureanddata':
66
                    // Check to see if they have pg_dump set up and if they do, use that
67
                    // instead of custom dump code
68
                    if ($misc->isDumpEnabled()) {
69
                        $dbexport_controller = new \PHPPgAdmin\Controller\DbexportController($this->getContainer());
70
                        return $dbexport_controller->render();
71
                    } else {
72
                        $format = $_REQUEST['sd_format'];
73
                        $clean  = isset($_REQUEST['sd_clean']);
74
                        $oids   = isset($_REQUEST['sd_oids']);
75
                    }
76
                    break;
77
            }
78
79
            // Make it do a download, if necessary
80
            if ($_REQUEST['output'] == 'download') {
81
                // Set headers.  MSIE is totally broken for SSL downloading, so
82
                // we need to have it download in-place as plain text
83
                if (strstr($_SERVER['HTTP_USER_AGENT'], 'MSIE') && isset($_SERVER['HTTPS'])) {
84
                    header('Content-Type: text/plain');
85
                } else {
86
                    header('Content-Type: application/download');
87
88
                    if (isset($extensions[$format])) {
89
                        $ext = $extensions[$format];
90
                    } else {
91
                        $ext = 'txt';
92
                    }
93
94
                    header('Content-Disposition: attachment; filename=dump.' . $ext);
95
                }
96
            } else {
97
                header('Content-Type: text/plain');
98
            }
99
100
            if (isset($_REQUEST['query'])) {
101
                $_REQUEST['query'] = trim(urldecode($_REQUEST['query']));
102
            }
103
104
            // Set the schema search path
105 View Code Duplication
            if (isset($_REQUEST['search_path'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
106
                $data->setSearchPath(array_map('trim', explode(',', $_REQUEST['search_path'])));
107
            }
108
109
            // Set up the dump transaction
110
            $status = $data->beginDump();
111
112
            // If the dump is not dataonly then dump the structure prefix
113
            if ($_REQUEST['what'] != 'dataonly') {
114
                echo $data->getTableDefPrefix($_REQUEST['table'], $clean);
115
            }
116
117
            // If the dump is not structureonly then dump the actual data
118
            if ($_REQUEST['what'] != 'structureonly') {
119
                // Get database encoding
120
                $dbEncoding = $data->getDatabaseEncoding();
121
122
                // Set fetch mode to NUM so that duplicate field names are properly returned
123
                $data->conn->setFetchMode(ADODB_FETCH_NUM);
124
125
                // Execute the query, if set, otherwise grab all rows from the table
126
                if (isset($_REQUEST['table'])) {
127
                    $rs = $data->dumpRelation($_REQUEST['table'], $oids);
128
                } else {
129
                    $rs = $data->conn->Execute($_REQUEST['query']);
130
                }
131
132
                if ($format == 'copy') {
133
                    $data->fieldClean($_REQUEST['table']);
134
                    echo "COPY \"{$_REQUEST['table']}\"";
135
                    if ($oids) {
136
                        echo ' WITH OIDS';
137
                    }
138
139
                    echo " FROM stdin;\n";
140
                    while (!$rs->EOF) {
141
                        $first = true;
142
                        while (list($k, $v) = each($rs->fields)) {
143
                            // Escape value
144
                            $v = $data->escapeBytea($v);
145
146
                            // We add an extra escaping slash onto octal encoded characters
147
                            $v = preg_replace('/\\\\([0-7]{3})/', '\\\\\1', $v);
148
                            if ($first) {
149
                                echo (is_null($v)) ? '\\N' : $v;
150
                                $first = false;
151
                            } else {
152
                                echo "\t", (is_null($v)) ? '\\N' : $v;
153
                            }
154
                        }
155
                        echo "\n";
156
                        $rs->moveNext();
157
                    }
158
                    echo "\\.\n";
159
                } elseif ($format == 'html') {
160
                    echo "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\r\n";
161
                    echo "<html xmlns=\"http://www.w3.org/1999/xhtml\">\r\n";
162
                    echo "<head>\r\n";
163
                    echo "\t<title></title>\r\n";
164
                    echo "\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\r\n";
165
                    echo "</head>\r\n";
166
                    echo "<body>\r\n";
167
                    echo "<table class=\"phppgadmin\">\r\n";
168
                    echo "\t<tr>\r\n";
169
                    if (!$rs->EOF) {
170
                        // Output header row
171
                        $j = 0;
172 View Code Duplication
                        foreach ($rs->fields as $k => $v) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
173
                            $finfo = $rs->fetchField($j++);
174
                            if ($finfo->name == $data->id && !$oids) {
175
                                continue;
176
                            }
177
178
                            echo "\t\t<th>", $misc->printVal($finfo->name, true), "</th>\r\n";
179
                        }
180
                    }
181
                    echo "\t</tr>\r\n";
182
                    while (!$rs->EOF) {
183
                        echo "\t<tr>\r\n";
184
                        $j = 0;
185 View Code Duplication
                        foreach ($rs->fields as $k => $v) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
186
                            $finfo = $rs->fetchField($j++);
187
                            if ($finfo->name == $data->id && !$oids) {
188
                                continue;
189
                            }
190
191
                            echo "\t\t<td>", $misc->printVal($v, true, $finfo->type), "</td>\r\n";
192
                        }
193
                        echo "\t</tr>\r\n";
194
                        $rs->moveNext();
195
                    }
196
                    echo "</table>\r\n";
197
                    echo "</body>\r\n";
198
                    echo "</html>\r\n";
199
                } elseif ($format == 'xml') {
200
                    echo "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n";
201
                    echo "<data>\n";
202
                    if (!$rs->EOF) {
203
                        // Output header row
204
                        $j = 0;
205
                        echo "\t<header>\n";
206
                        foreach ($rs->fields as $k => $v) {
207
                            $finfo = $rs->fetchField($j++);
208
                            $name  = htmlspecialchars($finfo->name);
209
                            $type  = htmlspecialchars($finfo->type);
210
                            echo "\t\t<column name=\"{$name}\" type=\"{$type}\" />\n";
211
                        }
212
                        echo "\t</header>\n";
213
                    }
214
                    echo "\t<records>\n";
215
                    while (!$rs->EOF) {
216
                        $j = 0;
217
                        echo "\t\t<row>\n";
218
                        foreach ($rs->fields as $k => $v) {
219
                            $finfo = $rs->fetchField($j++);
220
                            $name  = htmlspecialchars($finfo->name);
221
                            if (!is_null($v)) {
222
                                $v = htmlspecialchars($v);
223
                            }
224
225
                            echo "\t\t\t<column name=\"{$name}\"", (is_null($v) ? ' null="null"' : ''), ">{$v}</column>\n";
226
                        }
227
                        echo "\t\t</row>\n";
228
                        $rs->moveNext();
229
                    }
230
                    echo "\t</records>\n";
231
                    echo "</data>\n";
232
                } elseif ($format == 'sql') {
233
                    $data->fieldClean($_REQUEST['table']);
234
                    while (!$rs->EOF) {
235
                        echo "INSERT INTO \"{$_REQUEST['table']}\" (";
236
                        $first = true;
237
                        $j     = 0;
238
                        foreach ($rs->fields as $k => $v) {
239
                            $finfo = $rs->fetchField($j++);
240
                            $k     = $finfo->name;
241
                            // SQL (INSERT) format cannot handle oids
242
                            //                        if ($k == $data->id) continue;
243
                            // Output field
244
                            $data->fieldClean($k);
245
                            if ($first) {
246
                                echo "\"{$k}\"";
247
                            } else {
248
                                echo ", \"{$k}\"";
249
                            }
250
251
                            if (!is_null($v)) {
252
                                // Output value
253
                                // addCSlashes converts all weird ASCII characters to octal representation,
254
                                // EXCEPT the 'special' ones like \r \n \t, etc.
255
                                $v = addCSlashes($v, "\0..\37\177..\377");
256
                                // We add an extra escaping slash onto octal encoded characters
257
                                $v = preg_replace('/\\\\([0-7]{3})/', '\\\1', $v);
258
                                // Finally, escape all apostrophes
259
                                $v = str_replace("'", "''", $v);
260
                            }
261 View Code Duplication
                            if ($first) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
262
                                $values = (is_null($v) ? 'NULL' : "'{$v}'");
263
                                $first  = false;
264
                            } else {
265
                                $values .= ', ' . ((is_null($v) ? 'NULL' : "'{$v}'"));
266
                            }
267
                        }
268
                        echo ") VALUES ({$values});\n";
269
                        $rs->moveNext();
270
                    }
271
                } else {
272
                    switch ($format) {
273
                        case 'tab':
274
                            $sep = "\t";
275
                            break;
276
                        case 'csv':
277
                        default:
278
                            $sep = ',';
279
                            break;
280
                    }
281
                    if (!$rs->EOF) {
282
                        // Output header row
283
                        $first = true;
284
                        foreach ($rs->fields as $k => $v) {
285
                            $finfo = $rs->fetchField($k);
286
                            $v     = $finfo->name;
287
                            if (!is_null($v)) {
288
                                $v = str_replace('"', '""', $v);
289
                            }
290
291
                            if ($first) {
292
                                echo "\"{$v}\"";
293
                                $first = false;
294
                            } else {
295
                                echo "{$sep}\"{$v}\"";
296
                            }
297
                        }
298
                        echo "\r\n";
299
                    }
300
                    while (!$rs->EOF) {
301
                        $first = true;
302
                        foreach ($rs->fields as $k => $v) {
303
                            if (!is_null($v)) {
304
                                $v = str_replace('"', '""', $v);
305
                            }
306
307 View Code Duplication
                            if ($first) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
308
                                echo (is_null($v)) ? '"\\N"' : "\"{$v}\"";
309
                                $first = false;
310
                            } else {
311
                                echo is_null($v) ? "{$sep}\"\\N\"" : "{$sep}\"{$v}\"";
312
                            }
313
                        }
314
                        echo "\r\n";
315
                        $rs->moveNext();
316
                    }
317
                }
318
            }
319
320
            // If the dump is not dataonly then dump the structure suffix
321
            if ($_REQUEST['what'] != 'dataonly') {
322
                // Set fetch mode back to ASSOC for the table suffix to work
323
                $data->conn->setFetchMode(ADODB_FETCH_ASSOC);
324
                echo $data->getTableDefSuffix($_REQUEST['table']);
325
            }
326
327
            // Finish the dump transaction
328
            $status = $data->endDump();
329
        } else {
330
            return $this->doDefault();
331
        }
332
    }
333
334
    public function doDefault($msg = '')
0 ignored issues
show
Coding Style introduced by
doDefault uses the super-global variable $_REQUEST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
Coding Style introduced by
doDefault uses the super-global variable $_SESSION which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
335
    {
336
        $conf   = $this->conf;
337
        $misc   = $this->misc;
338
        $lang   = $this->lang;
339
        $data   = $misc->getDatabaseAccessor();
340
        $action = $this->action;
341
342
        if (!isset($_REQUEST['query']) or empty($_REQUEST['query'])) {
343
            $_REQUEST['query'] = $_SESSION['sqlquery'];
344
        }
345
346
        $this->printHeader($lang['strexport']);
347
        $this->printBody();
348
        $this->printTrail(isset($_REQUEST['subject']) ? $_REQUEST['subject'] : 'database');
349
        $this->printTitle($lang['strexport']);
350
        if (isset($msg)) {
351
            $this->printMsg($msg);
352
        }
353
354
        echo '<form action="' . SUBFOLDER . "/src/views/dataexport.php\" method=\"post\">\n";
355
        echo "<table>\n";
356
        echo "<tr><th class=\"data\">{$lang['strformat']}:</th><td><select name=\"d_format\">\n";
357
        // COPY and SQL require a table
358
        if (isset($_REQUEST['table'])) {
359
            echo "<option value=\"copy\">COPY</option>\n";
360
            echo "<option value=\"sql\">SQL</option>\n";
361
        }
362
        echo "<option value=\"csv\">CSV</option>\n";
363
        echo "<option value=\"tab\">{$lang['strtabbed']}</option>\n";
364
        echo "<option value=\"html\">XHTML</option>\n";
365
        echo "<option value=\"xml\">XML</option>\n";
366
        echo '</select></td></tr>';
367
        echo "</table>\n";
368
369
        echo "<h3>{$lang['stroptions']}</h3>\n";
370
        echo "<p><input type=\"radio\" id=\"output1\" name=\"output\" value=\"show\" checked=\"checked\" /><label for=\"output1\">{$lang['strshow']}</label>\n";
371
        echo "<br/><input type=\"radio\" id=\"output2\" name=\"output\" value=\"download\" /><label for=\"output2\">{$lang['strdownload']}</label></p>\n";
372
373
        echo "<p><input type=\"hidden\" name=\"action\" value=\"export\" />\n";
374
        echo "<input type=\"hidden\" name=\"what\" value=\"dataonly\" />\n";
375
        if (isset($_REQUEST['table'])) {
376
            echo '<input type="hidden" name="table" value="', htmlspecialchars($_REQUEST['table']), "\" />\n";
377
        }
378
        echo '<input type="hidden" name="query" value="', htmlspecialchars(urlencode($_REQUEST['query'])), "\" />\n";
379
        if (isset($_REQUEST['search_path'])) {
380
            echo '<input type="hidden" name="search_path" value="', htmlspecialchars($_REQUEST['search_path']), "\" />\n";
381
        }
382
        echo $misc->form;
383
        echo "<input type=\"submit\" value=\"{$lang['strexport']}\" /></p>\n";
384
        echo "</form>\n";
385
386
        $this->printFooter();
387
    }
388
}
389