Passed
Pull Request — develop (#92)
by Felipe
04:47
created

SqlController::doFooter()   C

Complexity

Conditions 11
Paths 80

Size

Total Lines 97
Code Lines 51

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 11
eloc 51
nc 80
nop 2
dl 0
loc 97
rs 5.2653
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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 SqlController extends BaseController
13
{
14
    public $controller_name = 'SqlController';
15
    public $query           = '';
16
    public $subject         = '';
17
    public $start_time;
18
    public $duration;
19
20
    /**
21
     * Default method to render the controller according to the action parameter.
22
     */
23
    public function render()
24
    {
25
        $conf = $this->conf;
0 ignored issues
show
Unused Code introduced by
The assignment to $conf is dead and can be removed.
Loading history...
26
        $lang = $this->lang;
27
28
        $data = $this->misc->getDatabaseAccessor();
29
30
        set_time_limit(0);
31
32
        // We need to store the query in a session for editing purposes
33
        // We avoid GPC vars to avoid truncating long queries
34
        if (isset($_REQUEST['subject']) && 'history' == $_REQUEST['subject']) {
35
            // Or maybe we came from the history popup
36
            $_SESSION['sqlquery'] = $_SESSION['history'][$_REQUEST['server']][$_REQUEST['database']][$_GET['queryid']]['query'];
37
            $this->query          = $_SESSION['sqlquery'];
38
        } elseif (isset($_POST['query'])) {
39
            // Or maybe we came from an sql form
40
            $_SESSION['sqlquery'] = $_POST['query'];
41
            $this->query          = $_SESSION['sqlquery'];
42
        } else {
43
            echo 'could not find the query!!';
44
        }
45
46
        // Pagination maybe set by a get link that has it as FALSE,
47
        // if that's the case, unset the variable.
48
        if (isset($_REQUEST['paginate']) && 'f' == $_REQUEST['paginate']) {
49
            unset($_REQUEST['paginate'], $_POST['paginate'], $_GET['paginate']);
50
        }
51
52
        if (isset($_REQUEST['subject'])) {
53
            $this->subject = $_REQUEST['subject'];
54
        }
55
56
        // Check to see if pagination has been specified. In that case, send to display
57
        // script for pagination
58
        // if a file is given or the request is an explain, do not paginate
59
        if (isset($_REQUEST['paginate']) && !(isset($_FILES['script']) && $_FILES['script']['size'] > 0) && (0 == preg_match('/^\s*explain/i', $this->query))) {
60
            //if (!(isset($_FILES['script']) && $_FILES['script']['size'] > 0)) {
61
62
            $display_controller = new DisplayController($this->getContainer());
63
64
            return $display_controller->render();
65
        }
66
67
        $this->printHeader($lang['strqueryresults'], null, true, 'header_sqledit.twig');
68
        $this->printBody();
69
        $this->printTrail('database');
70
        $this->printTitle($lang['strqueryresults']);
71
72
        // Set the schema search path
73
        if (isset($_REQUEST['search_path'])) {
74
            if (0 != $data->setSearchPath(array_map('trim', explode(',', $_REQUEST['search_path'])))) {
75
                return $this->printFooter();
76
            }
77
        }
78
79
        // May as well try to time the query
80
        if (function_exists('microtime')) {
81
            list($usec, $sec) = explode(' ', microtime());
82
            $this->start_time = ((float) $usec + (float) $sec);
83
        }
84
85
        $this->doDefault();
86
87
        $this->doFooter(true, 'footer_sqledit.twig');
88
    }
89
90
    public function doDefault()
1 ignored issue
show
Coding Style introduced by
Missing function doc comment
Loading history...
91
    {
92
        $conf        = $this->conf;
0 ignored issues
show
Unused Code introduced by
The assignment to $conf is dead and can be removed.
Loading history...
93
        $this->misc  = $this->misc;
94
        $lang        = $this->lang;
0 ignored issues
show
Unused Code introduced by
The assignment to $lang is dead and can be removed.
Loading history...
95
        $data        = $this->misc->getDatabaseAccessor();
0 ignored issues
show
Unused Code introduced by
The assignment to $data is dead and can be removed.
Loading history...
96
        $_connection = $this->misc->getConnection();
97
98
        try {
99
            // Execute the query.  If it's a script upload, special handling is necessary
100
            if (isset($_FILES['script']) && $_FILES['script']['size'] > 0) {
101
                return $this->execute_script();
102
            }
103
104
            return $this->execute_query();
105
        } catch (\PHPPgAdmin\ADOdbException $e) {
106
            $message   = $e->getMessage();
107
            $trace     = $e->getTraceAsString();
108
            $lastError = $_connection->getLastError();
109
            $this->prtrace(['message' => $message, 'trace' => $trace, 'lastError' => $lastError]);
110
111
            return null;
112
        }
113
    }
114
115
    private function execute_script()
2 ignored issues
show
Coding Style introduced by
Private method name "SqlController::execute_script" must be prefixed with an underscore
Loading history...
Coding Style introduced by
Missing function doc comment
Loading history...
116
    {
117
        $conf        = $this->conf;
0 ignored issues
show
Unused Code introduced by
The assignment to $conf is dead and can be removed.
Loading history...
118
        $misc        = $this->misc;
119
        $lang        = $this->lang;
120
        $data        = $this->misc->getDatabaseAccessor();
121
        $_connection = $this->misc->getConnection();
122
123
        /**
124
         * This is a callback function to display the result of each separate query.
125
         *
126
         * @param ADORecordSet $rs The recordset returned by the script execetor
127
         */
128
        $sqlCallback = function ($query, $rs, $lineno) use ($data, $misc, $lang, $_connection) {
129
            // Check if $rs is false, if so then there was a fatal error
130
            if (false === $rs) {
131
                echo htmlspecialchars($_FILES['script']['name']), ':', $lineno, ': ', nl2br(htmlspecialchars($_connection->getLastError())), "<br/>\n";
132
            } else {
133
                // Print query results
134
                switch (pg_result_status($rs)) {
135
                    case PGSQL_TUPLES_OK:
136
                        // If rows returned, then display the results
137
                        $num_fields = pg_numfields($rs);
138
                        echo "<p><table>\n<tr>";
139
                        for ($k = 0; $k < $num_fields; ++$k) {
140
                            echo '<th class="data">', $misc->printVal(pg_fieldname($rs, $k)), '</th>';
141
                        }
142
143
                        $i   = 0;
144
                        $row = pg_fetch_row($rs);
145
                        while (false !== $row) {
146
                            $id = (0 == ($i % 2) ? '1' : '2');
147
                            echo "<tr class=\"data{$id}\">\n";
148
                            foreach ($row as $k => $v) {
149
                                echo '<td style="white-space:nowrap;">', $misc->printVal($v, pg_fieldtype($rs, $k), ['null' => true]), '</td>';
150
                            }
151
                            echo "</tr>\n";
152
                            $row = pg_fetch_row($rs);
153
                            ++$i;
154
                        }
155
156
                        echo "</table><br/>\n";
157
                        echo $i, " {$lang['strrows']}</p>\n";
158
159
                        break;
160
                    case PGSQL_COMMAND_OK:
161
                        // If we have the command completion tag
162
                        if (version_compare(phpversion(), '4.3', '>=')) {
163
                            echo htmlspecialchars(pg_result_status($rs, PGSQL_STATUS_STRING)), "<br/>\n";
164
                        }
165
                        // Otherwise if any rows have been affected
166
                        elseif ($data->conn->Affected_Rows() > 0) {
0 ignored issues
show
Coding Style introduced by
Expected "} elseif (...) \n"; found "\n // Otherwise if any rows have been affected\n elseif (...) {\n"
Loading history...
167
                            echo $data->conn->Affected_Rows(), " {$lang['strrowsaff']}<br/>\n";
168
                        }
169
                        // Otherwise output nothing...
170
                        break;
171
                    case PGSQL_EMPTY_QUERY:
172
                        break;
173
                    default:
174
                        break;
175
                }
176
            }
177
        };
178
179
        return $data->executeScript('script', $sqlCallback);
180
    }
181
182
    private function execute_query()
2 ignored issues
show
Coding Style introduced by
Missing function doc comment
Loading history...
Coding Style introduced by
Private method name "SqlController::execute_query" must be prefixed with an underscore
Loading history...
183
    {
184
        $conf = $this->conf;
0 ignored issues
show
Unused Code introduced by
The assignment to $conf is dead and can be removed.
Loading history...
185
186
        $lang = $this->lang;
187
        $data = $this->misc->getDatabaseAccessor();
188
189
        // Set fetch mode to NUM so that duplicate field names are properly returned
190
        $data->conn->setFetchMode(ADODB_FETCH_NUM);
191
192
        $rs = $data->conn->Execute($this->query);
193
194
        echo '<form method="post" id="sqlform" action="'.$_SERVER['REQUEST_URI'].'">';
195
        echo '<textarea width="90%" name="query"  id="query" rows="5" cols="100" resizable="true">';
196
197
        echo htmlspecialchars($this->query);
198
        echo '</textarea><br>';
199
        echo $this->misc->setForm();
200
        echo '<input type="submit"/></form>';
201
202
        // $rs will only be an object if there is no error
203
        if (is_object($rs)) {
204
            // Request was run, saving it in history
205
            if (!isset($_REQUEST['nohistory'])) {
206
                $this->misc->saveScriptHistory($this->query);
207
            }
208
209
            // Now, depending on what happened do various things
210
211
            // First, if rows returned, then display the results
212
            if ($rs->recordCount() > 0) {
213
                echo "<table>\n<tr>";
214
                foreach ($rs->fields as $k => $v) {
215
                    $finfo = $rs->fetchField($k);
216
                    echo '<th class="data">', $this->misc->printVal($finfo->name), '</th>';
217
                }
218
                echo "</tr>\n";
219
                $i = 0;
220
                while (!$rs->EOF) {
221
                    $id = (0 == ($i % 2) ? '1' : '2');
222
                    echo "<tr class=\"data{$id}\">\n";
223
                    foreach ($rs->fields as $k => $v) {
224
                        $finfo = $rs->fetchField($k);
225
                        echo '<td style="white-space:nowrap;">', $this->misc->printVal($v, $finfo->type, ['null' => true]), '</td>';
226
                    }
227
                    echo "</tr>\n";
228
                    $rs->moveNext();
229
                    ++$i;
230
                }
231
                echo "</table>\n";
232
                echo '<p>', $rs->recordCount(), " {$lang['strrows']}</p>\n";
233
            } elseif ($data->conn->Affected_Rows() > 0) {
234
                // Otherwise if any rows have been affected
235
                echo '<p>', $data->conn->Affected_Rows(), " {$lang['strrowsaff']}</p>\n";
236
            } else {
237
                // Otherwise nodata to print
238
                echo '<p>', $lang['strnodata'], "</p>\n";
239
            }
240
        }
241
    }
242
243
    private function doFooter($doBody = true, $template = 'footer.twig')
2 ignored issues
show
Coding Style introduced by
Missing function doc comment
Loading history...
Coding Style introduced by
Private method name "SqlController::doFooter" must be prefixed with an underscore
Loading history...
244
    {
245
        $conf = $this->conf;
246
247
        $lang = $this->lang;
248
        $data = $this->misc->getDatabaseAccessor();
249
250
        // May as well try to time the query
251
        if (null !== $this->start_time) {
252
            list($usec, $sec) = explode(' ', microtime());
253
            $end_time         = ((float) $usec + (float) $sec);
254
            // Get duration in milliseconds, round to 3dp's
255
            $this->duration = number_format(($end_time - $this->start_time) * 1000, 3);
256
        }
257
258
        // Reload the browser as we may have made schema changes
259
        $this->misc->setReloadBrowser(true);
260
261
        // Display duration if we know it
262
        if (null !== $this->duration) {
263
            echo '<p>', sprintf($lang['strruntime'], $this->duration), "</p>\n";
264
        }
265
266
        echo "<p>{$lang['strsqlexecuted']}</p>\n";
267
268
        $navlinks = [];
269
        $fields   = [
270
            'server'   => $_REQUEST['server'],
271
            'database' => $_REQUEST['database'],
272
        ];
273
274
        if (isset($_REQUEST['schema'])) {
275
            $fields['schema'] = $_REQUEST['schema'];
276
        }
277
278
        // Return
279
        if (isset($_REQUEST['return'])) {
280
            $urlvars          = $this->misc->getSubjectParams($_REQUEST['return']);
281
            $navlinks['back'] = [
282
                'attr' => [
283
                    'href' => [
284
                        'url'     => $urlvars['url'],
285
                        'urlvars' => $urlvars['params'],
286
                    ],
287
                ],
288
                'content' => $lang['strback'],
289
            ];
290
        }
291
292
        // Edit
293
        $navlinks['alter'] = [
294
            'attr' => [
295
                'href' => [
296
                    'url'     => 'database.php',
297
                    'urlvars' => array_merge($fields, [
1 ignored issue
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
298
                        'action' => 'sql',
299
                    ]),
1 ignored issue
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
300
                ],
301
            ],
302
            'content' => $lang['streditsql'],
303
        ];
304
305
        // Create view and download
306
        if ('' !== $this->query && isset($rs) && is_object($rs) && $rs->recordCount() > 0) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $rs seems to never exist and therefore isset should always be false.
Loading history...
307
            // Report views don't set a schema, so we need to disable create view in that case
308
            if (isset($_REQUEST['schema'])) {
309
                $navlinks['createview'] = [
310
                    'attr' => [
311
                        'href' => [
312
                            'url'     => 'views.php',
313
                            'urlvars' => array_merge($fields, [
1 ignored issue
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
314
                                'action' => 'create',
315
                            ]),
1 ignored issue
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
316
                        ],
317
                    ],
318
                    'content' => $lang['strcreateview'],
319
                ];
320
            }
321
322
            if (isset($_REQUEST['search_path'])) {
323
                $fields['search_path'] = $_REQUEST['search_path'];
324
            }
325
326
            $navlinks['download'] = [
327
                'attr' => [
328
                    'href' => [
329
                        'url'     => 'dataexport.php',
330
                        'urlvars' => $fields,
331
                    ],
332
                ],
333
                'content' => $lang['strdownload'],
334
            ];
335
        }
336
337
        $this->printNavLinks($navlinks, 'sql-form', get_defined_vars());
338
339
        return $this->printFooter($doBody, $template);
340
    }
341
}
342