Passed
Push — master ( 0fcbbc...404f24 )
by Felipe
14:10 queued 09:33
created

IndexesController::doSaveCreateIndex()   C

Complexity

Conditions 8
Paths 32

Size

Total Lines 41
Code Lines 28

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 8
eloc 28
nc 32
nop 0
dl 0
loc 41
rs 5.3846
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
use PHPPgAdmin\Decorators\Decorator;
10
11
/**
12
 * Base controller class.
13
 */
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...
14
class IndexesController extends BaseController
15
{
16
    public $controller_name = 'IndexesController';
17
18
    /**
19
     * Default method to render the controller according to the action parameter.
20
     */
21
    public function render()
22
    {
23
        $lang = $this->lang;
24
25
        $action = $this->action;
26
        if ('tree' == $action) {
27
            return $this->doTree();
28
        }
29
30
        $this->printHeader($lang['strindexes'], '<script src="' . \SUBFOLDER . '/js/indexes.js" type="text/javascript"></script>');
31
32
        if ('create_index' == $action || 'save_create_index' == $action) {
33
            echo '<body onload="init();">';
34
        } else {
35
            $this->printBody();
36
        }
37
38
        switch ($action) {
39
            case 'cluster_index':
40
                if (isset($_POST['cluster'])) {
41
                    $this->doClusterIndex(false);
42
                } else {
43
                    $this->doDefault();
44
                }
45
46
                break;
47
            case 'confirm_cluster_index':
48
                $this->doClusterIndex(true);
49
50
                break;
51
            case 'reindex':
52
                $this->doReindex();
53
54
                break;
55
            case 'save_create_index':
56
                if (isset($_POST['cancel'])) {
57
                    $this->doDefault();
58
                } else {
59
                    $this->doSaveCreateIndex();
60
                }
61
62
                break;
63
            case 'create_index':
64
                $this->doCreateIndex();
65
66
                break;
67
            case 'drop_index':
68
                if (isset($_POST['drop'])) {
69
                    $this->doDropIndex(false);
70
                } else {
71
                    $this->doDefault();
72
                }
73
74
                break;
75
            case 'confirm_drop_index':
76
                $this->doDropIndex(true);
77
78
                break;
79
            default:
80
                $this->doDefault();
81
82
                break;
83
        }
84
85
        return $this->printFooter();
86
    }
87
88
    public function doDefault($msg = '')
1 ignored issue
show
Coding Style introduced by
Missing function doc comment
Loading history...
89
    {
90
        $lang = $this->lang;
91
        $data = $this->misc->getDatabaseAccessor();
92
93
        $indPre = function (&$rowdata, $actions) use ($data, $lang) {
94
            if ($data->phpBool($rowdata->fields['indisprimary'])) {
95
                $rowdata->fields['+constraints'] = $lang['strprimarykey'];
96
                $actions['drop']['disable']      = true;
97
            } elseif ($data->phpBool($rowdata->fields['indisunique'])) {
98
                $rowdata->fields['+constraints'] = $lang['struniquekey'];
99
                $actions['drop']['disable']      = true;
100
            } else {
101
                $rowdata->fields['+constraints'] = '';
102
            }
103
104
            return $actions;
105
        };
106
        if (!isset($_REQUEST['subject'])) {
107
            $_REQUEST['subject'] = 'table';
108
        }
109
110
        $subject = urlencode($_REQUEST['subject']);
111
        $object  = urlencode($_REQUEST[$_REQUEST['subject']]);
112
113
        $this->printTrail($subject);
114
        $this->printTabs($subject, 'indexes');
115
        $this->printMsg($msg);
116
117
        $indexes = $data->getIndexes($_REQUEST[$_REQUEST['subject']]);
118
119
        $columns = [
120
            'index'       => [
121
                'title' => $lang['strname'],
122
                'field' => Decorator::field('indname'),
123
            ],
124
            'definition'  => [
125
                'title' => $lang['strdefinition'],
126
                'field' => Decorator::field('inddef'),
127
            ],
128
            'constraints' => [
129
                'title'  => $lang['strconstraints'],
130
                'field'  => Decorator::field('+constraints'),
131
                'type'   => 'verbatim',
132
                'params' => ['align' => 'center'],
133
            ],
134
            'clustered'   => [
135
                'title' => $lang['strclustered'],
136
                'field' => Decorator::field('indisclustered'),
137
                'type'  => 'yesno',
138
            ],
139
            'actions'     => [
140
                'title' => $lang['stractions'],
141
            ],
142
            'comment'     => [
143
                'title' => $lang['strcomment'],
144
                'field' => Decorator::field('idxcomment'),
145
            ],
146
        ];
147
148
        $url = (\SUBFOLDER ? '/' . \SUBFOLDER : '') . '/src/views/indexes';
149
150
        $actions = [
151
            'cluster' => [
152
                'content' => $lang['strclusterindex'],
153
                'attr'    => [
154
                    'href' => [
155
                        'url'     => $url,
156
                        'urlvars' => [
157
                            'action'  => 'confirm_cluster_index',
158
                            'subject' => $subject,
159
                            $subject  => $object,
160
                            'index'   => Decorator::field('indname'),
161
                        ],
162
                    ],
163
                ],
164
            ],
165
            'reindex' => [
166
                'content' => $lang['strreindex'],
167
                'attr'    => [
168
                    'href' => [
169
                        'url'     => $url,
170
                        'urlvars' => [
171
                            'action'  => 'reindex',
172
                            'subject' => $subject,
173
                            $subject  => $object,
174
                            'index'   => Decorator::field('indname'),
175
                        ],
176
                    ],
177
                ],
178
            ],
179
            'drop'    => [
180
                'content' => $lang['strdrop'],
181
                'attr'    => [
182
                    'href' => [
183
                        'url'     => $url,
184
                        'urlvars' => [
185
                            'action'  => 'confirm_drop_index',
186
                            'subject' => $subject,
187
                            $subject  => $object,
188
                            'index'   => Decorator::field('indname'),
189
                        ],
190
                    ],
191
                ],
192
            ],
193
        ];
194
195
        echo $this->printTable($indexes, $columns, $actions, 'indexes-indexes', $lang['strnoindexes'], $indPre);
196
197
        $this->printNavLinks([
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...
198
            'create' => [
199
                'attr'    => [
200
                    'href' => [
201
                        'url'     => 'indexes.php',
202
                        'urlvars' => [
203
                            'action'   => 'create_index',
204
                            'server'   => $_REQUEST['server'],
205
                            'database' => $_REQUEST['database'],
206
                            'schema'   => $_REQUEST['schema'],
207
                            $subject   => $object,
208
                            'subject'  => $subject,
209
                        ],
210
                    ],
211
                ],
212
                'content' => $lang['strcreateindex'],
213
            ],
214
        ], 'indexes-indexes', get_defined_vars());
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...
215
    }
216
217
    public function doTree()
1 ignored issue
show
Coding Style introduced by
Missing function doc comment
Loading history...
218
    {
219
        $lang = $this->lang;
0 ignored issues
show
Unused Code introduced by
The assignment to $lang is dead and can be removed.
Loading history...
220
        $data = $this->misc->getDatabaseAccessor();
221
        if (!isset($_REQUEST['subject'])) {
222
            $_REQUEST['subject'] = 'table';
223
        }
224
225
        $subject = urlencode($_REQUEST['subject']);
226
        $object  = urlencode($_REQUEST[$_REQUEST['subject']]);
227
228
        $indexes = $data->getIndexes($object);
229
230
        $reqvars = $this->misc->getRequestVars($subject);
0 ignored issues
show
Unused Code introduced by
The assignment to $reqvars is dead and can be removed.
Loading history...
231
232
        $getIcon = function ($f) {
233
            if ('t' == $f['indisprimary']) {
234
                return 'PrimaryKey';
235
            }
236
237
            if ('t' == $f['indisunique']) {
238
                return 'UniqueConstraint';
239
            }
240
241
            return 'Index';
242
        };
243
244
        $attrs = [
245
            'text' => Decorator::field('indname'),
246
            'icon' => Decorator::callback($getIcon),
247
        ];
248
249
        return $this->printTree($indexes, $attrs, 'indexes');
250
    }
251
252
    /**
253
     * Show confirmation of cluster index and perform actual cluster.
254
     *
255
     * @param mixed $confirm
1 ignored issue
show
Coding Style introduced by
Missing parameter comment
Loading history...
256
     */
257
    public function doClusterIndex($confirm)
258
    {
259
        $lang = $this->lang;
260
        $data = $this->misc->getDatabaseAccessor();
261
262
        if (!isset($_REQUEST['subject'])) {
263
            $_REQUEST['subject'] = 'table';
264
        }
265
        $subject = urlencode($_REQUEST['subject']);
266
        $object  = urlencode($_REQUEST[$subject]);
267
268
        if ($confirm) {
269
            // Default analyze to on
270
            $_REQUEST['analyze'] = true;
271
272
            $this->printTrail('index');
273
            $this->printTitle($lang['strclusterindex'], 'pg.index.cluster');
274
275
            echo '<p>', sprintf($lang['strconfcluster'], $this->misc->printVal($_REQUEST['index'])), '</p>' . "\n";
276
277
            echo '<form action="' . \SUBFOLDER . '/src/views/indexes.php" method="post">' . "\n";
278
            echo '<p><input type="checkbox" id="analyze" name="analyze"', (isset($_REQUEST['analyze']) ? ' checked="checked"' : ''), ' />';
279
            echo "<label for=\"analyze\">{$lang['stranalyze']}</label></p>" . "\n";
280
            echo '<input type="hidden" name="action" value="cluster_index" />' . "\n";
281
            echo '<input type="hidden" name="table" value="', htmlspecialchars($object), '" />' . "\n";
282
            echo '<input type="hidden" name="index" value="', htmlspecialchars($_REQUEST['index']), '" />' . "\n";
283
            echo $this->misc->form;
284
            echo "<input type=\"submit\" name=\"cluster\" value=\"{$lang['strclusterindex']}\" />" . "\n";
285
            echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" />" . "\n";
286
            echo '</form>' . "\n";
287
        } else {
288
            set_time_limit(0);
289
            list($status, $sql) = $data->clusterIndex($object, $_POST['index']);
290
            if (0 == $status) {
291
                if (isset($_POST['analyze'])) {
292
                    $status = $data->analyzeDB($object);
293
                    if (0 == $status) {
294
                        $this->doDefault($sql . '<br>' . $lang['strclusteredgood'] . ' ' . $lang['stranalyzegood']);
295
                    } else {
296
                        $this->doDefault($sql . '<br>' . $lang['stranalyzebad']);
297
                    }
298
                } else {
299
                    $this->doDefault($sql . '<br>' . $lang['strclusteredgood']);
300
                }
301
            } else {
302
                $this->doDefault($sql . '<br>' . $lang['strclusteredbad']);
303
            }
304
        }
305
    }
306
307
    public function doReindex()
1 ignored issue
show
Coding Style introduced by
Missing function doc comment
Loading history...
308
    {
309
        $lang = $this->lang;
310
        $data = $this->misc->getDatabaseAccessor();
311
        set_time_limit(0);
312
        $status = $data->reindex('INDEX', $_REQUEST['index']);
313
        if (0 == $status) {
314
            $this->doDefault($lang['strreindexgood']);
315
        } else {
316
            $this->doDefault($lang['strreindexbad']);
317
        }
318
    }
319
320
    /**
321
     * Displays a screen where they can enter a new index.
322
     *
323
     * @param mixed $msg
1 ignored issue
show
Coding Style introduced by
Missing parameter comment
Loading history...
324
     */
325
    public function doCreateIndex($msg = '')
326
    {
327
        $lang = $this->lang;
328
        $data = $this->misc->getDatabaseAccessor();
329
330
        if (!isset($_REQUEST['subject'])) {
331
            $_REQUEST['subject'] = 'table';
332
        }
333
        $subject = urlencode($_REQUEST['subject']);
334
        $object  = urlencode($_REQUEST[$subject]);
335
336
        if (!isset($_POST['formIndexName'])) {
337
            $_POST['formIndexName'] = '';
338
        }
339
340
        if (!isset($_POST['formIndexType'])) {
341
            $_POST['formIndexType'] = null;
342
        }
343
344
        if (!isset($_POST['formCols'])) {
345
            $_POST['formCols'] = '';
346
        }
347
348
        if (!isset($_POST['formWhere'])) {
349
            $_POST['formWhere'] = '';
350
        }
351
352
        if (!isset($_POST['formSpc'])) {
353
            $_POST['formSpc'] = '';
354
        }
355
356
        $attrs = $data->getTableAttributes($object);
357
        // Fetch all tablespaces from the database
358
        if ($data->hasTablespaces()) {
359
            $tablespaces = $data->getTablespaces();
360
        }
361
        $this->prtrace('tablespaces', $tablespaces->recordCount());
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $tablespaces does not seem to be defined for all execution paths leading up to this point.
Loading history...
362
        $this->printTrail($subject);
363
        $this->printTitle($lang['strcreateindex'], 'pg.index.create');
364
        $this->printMsg($msg);
365
366
        $selColumns = new \PHPPgAdmin\XHtml\XHtmlSelect('TableColumnList', true, 10);
367
        $selColumns->set_style('width: 10em;');
368
369
        if ($attrs->recordCount() > 0) {
370
            while (!$attrs->EOF) {
371
                $attname = new \PHPPgAdmin\XHtml\XHtmlOption($attrs->fields['attname']);
372
                $selColumns->add($attname);
373
                $attrs->moveNext();
374
            }
375
        }
376
377
        $selIndex = new \PHPPgAdmin\XHtml\XHtmlSelect('IndexColumnList[]', true, 10);
378
        $selIndex->set_style('width: 10em;');
379
        $selIndex->set_attribute('id', 'IndexColumnList');
380
        $buttonAdd = new \PHPPgAdmin\XHtml\XHtmlButton('add', '>>');
381
        $buttonAdd->set_attribute('onclick', 'buttonPressed(this);');
382
        $buttonAdd->set_attribute('type', 'button');
383
384
        $buttonRemove = new \PHPPgAdmin\XHtml\XHtmlButton('remove', '<<');
385
        $buttonRemove->set_attribute('onclick', 'buttonPressed(this);');
386
        $buttonRemove->set_attribute('type', 'button');
387
388
        echo '<form onsubmit="doSelectAll();" name="formIndex" action="indexes.php" method="post">' . "\n";
389
390
        echo '<table>' . "\n";
391
        echo '<tr><th class="data required" colspan="3">' . $lang['strindexname'] . '</th></tr>';
392
        echo '<tr>';
393
        echo '<td class="data1" colspan="3">';
394
        echo '<input type="text" name="formIndexName" size="32" maxlength="' . $data->_maxNameLen . '" value="' . htmlspecialchars($_POST['formIndexName']) . '" />';
395
        echo '</td></tr>';
396
        echo '<tr><th class="data">' . $lang['strtablecolumnlist'] . '</th><th class="data">&nbsp;</th>';
397
        echo '<th class="data required">' . $lang['strindexcolumnlist'] . '</th></tr>' . "\n";
398
        echo '<tr><td class="data1">' . $selColumns->fetch() . '</td>' . "\n";
399
        echo '<td class="data1">' . $buttonRemove->fetch() . $buttonAdd->fetch() . '</td>';
400
        echo '<td class="data1">' . $selIndex->fetch() . '</td></tr>' . "\n";
401
        echo '</table>' . "\n";
402
403
        echo '<table> ' . "\n";
404
        echo '<tr>';
405
        echo '<th class="data left required" scope="row">' . $lang['strindextype'] . '</th>';
406
        echo '<td class="data1"><select name="formIndexType">';
407
        foreach ($data->typIndexes as $v) {
408
            echo '<option value="', htmlspecialchars($v), '"',
409
            ($v == $_POST['formIndexType']) ? ' selected="selected"' : '', '>', htmlspecialchars($v), '</option>' . "\n";
410
        }
411
        echo '</select></td></tr>' . "\n";
412
        echo '<tr>';
413
        echo "<th class=\"data left\" scope=\"row\"><label for=\"formUnique\">{$lang['strunique']}</label></th>";
414
        echo '<td class="data1"><input type="checkbox" id="formUnique" name="formUnique"', (isset($_POST['formUnique']) ? 'checked="checked"' : ''), ' /></td>';
415
        echo '</tr>';
416
        echo '<tr>';
417
        echo "<th class=\"data left\" scope=\"row\">{$lang['strwhere']}</th>";
418
        echo '<td class="data1">(<input name="formWhere" size="32" maxlength="' . $data->_maxNameLen . '" value="' . htmlspecialchars($_POST['formWhere']) . '" />)</td>';
419
        echo '</tr>';
420
421
        // Tablespace (if there are any)
422
        if ($data->hasTablespaces() && $tablespaces->recordCount() > 0) {
423
            echo "\t<tr>\n\t\t<th class=\"data left\">{$lang['strtablespace']}</th>" . "\n";
424
            echo "\t\t<td class=\"data1\">\n\t\t\t<select name=\"formSpc\">" . "\n";
425
            // Always offer the default (empty) option
426
            echo "\t\t\t\t<option value=\"\"",
427
            ('' == $_POST['formSpc']) ? ' selected="selected"' : '', '></option>' . "\n";
428
            // Display all other tablespaces
429
            while (!$tablespaces->EOF) {
430
                $spcname = htmlspecialchars($tablespaces->fields['spcname']);
431
                echo "\t\t\t\t<option value=\"{$spcname}\"",
432
                ($spcname == $_POST['formSpc']) ? ' selected="selected"' : '', ">{$spcname}</option>" . "\n";
433
                $tablespaces->moveNext();
434
            }
435
            echo "\t\t\t</select>\n\t\t</td>\n\t</tr>" . "\n";
436
        }
437
438
        if ($data->hasConcurrentIndexBuild()) {
439
            echo '<tr>';
440
            echo "<th class=\"data left\" scope=\"row\"><label for=\"formConcur\">{$lang['strconcurrently']}</label></th>";
441
            echo '<td class="data1"><input type="checkbox" id="formConcur" name="formConcur"', (isset($_POST['formConcur']) ? 'checked="checked"' : ''), ' /></td>';
442
            echo '</tr>';
443
        }
444
445
        echo '</table>';
446
447
        echo '<p><input type="hidden" name="action" value="save_create_index" />' . "\n";
448
        echo $this->misc->form;
449
        echo '<input type="hidden" name="subject" value="', htmlspecialchars($subject), '" />' . "\n";
450
        echo '<input type="hidden" name="' . $subject . '" value="', htmlspecialchars($object), '" />' . "\n";
451
        echo "<input type=\"submit\" value=\"{$lang['strcreate']}\" />" . "\n";
452
        echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" /></p>" . "\n";
453
        echo '</form>' . "\n";
454
    }
455
456
    /**
457
     * Actually creates the new index in the database.
458
     *
459
     * @@ Note: this function can't handle columns with commas in them
460
     */
461
    public function doSaveCreateIndex()
462
    {
463
        $lang = $this->lang;
464
        $data = $this->misc->getDatabaseAccessor();
465
466
        if (!isset($_POST['subject'])) {
467
            $_POST['subject'] = 'table';
468
        }
469
        $subject = urlencode($_POST['subject']);
470
        $object  = urlencode($_POST[$subject]);
471
472
        // Handle databases that don't have partial indexes
473
        if (!isset($_POST['formWhere'])) {
474
            $_POST['formWhere'] = '';
475
        }
476
477
        // Default tablespace to null if it isn't set
478
        if (!isset($_POST['formSpc'])) {
479
            $_POST['formSpc'] = null;
480
        }
481
482
        // Check that they've given a name and at least one column
483
        if ('' == $_POST['formIndexName']) {
484
            $this->doCreateIndex($lang['strindexneedsname']);
485
        } elseif (!isset($_POST['IndexColumnList']) || '' == $_POST['IndexColumnList']) {
486
            $this->doCreateIndex($lang['strindexneedscols']);
487
        } else {
488
            $status = $data->createIndex(
489
                $_POST['formIndexName'],
490
                $object,
491
                $_POST['IndexColumnList'],
492
                $_POST['formIndexType'],
493
                isset($_POST['formUnique']),
494
                $_POST['formWhere'],
495
                $_POST['formSpc'],
496
                isset($_POST['formConcur'])
497
            );
498
            if (0 == $status) {
499
                $this->doDefault($lang['strindexcreated']);
500
            } else {
501
                $this->doCreateIndex($lang['strindexcreatedbad']);
502
            }
503
        }
504
    }
505
506
    /**
507
     * Show confirmation of drop index and perform actual drop.
508
     *
509
     * @param mixed $confirm
1 ignored issue
show
Coding Style introduced by
Missing parameter comment
Loading history...
510
     */
511
    public function doDropIndex($confirm)
512
    {
513
        $lang = $this->lang;
514
        $data = $this->misc->getDatabaseAccessor();
515
516
        if (!isset($_REQUEST['subject'])) {
517
            $_REQUEST['subject'] = 'table';
518
        }
519
        $subject = urlencode($_REQUEST['subject']);
0 ignored issues
show
Unused Code introduced by
The assignment to $subject is dead and can be removed.
Loading history...
520
        $object  = urlencode($_REQUEST[$_REQUEST['subject']]);
521
522
        if ($confirm) {
523
            $this->printTrail('index');
524
            $this->printTitle($lang['strdrop'], 'pg.index.drop');
525
526
            echo '<p>', sprintf($lang['strconfdropindex'], $this->misc->printVal($_REQUEST['index'])), '</p>' . "\n";
527
528
            echo '<form action="' . \SUBFOLDER . '/src/views/indexes.php" method="post">' . "\n";
529
            echo '<input type="hidden" name="action" value="drop_index" />' . "\n";
530
            echo '<input type="hidden" name="table" value="', htmlspecialchars($object), '" />' . "\n";
531
            echo '<input type="hidden" name="index" value="', htmlspecialchars($_REQUEST['index']), '" />' . "\n";
532
            echo $this->misc->form;
533
            echo "<p><input type=\"checkbox\" id=\"cascade\" name=\"cascade\" /> <label for=\"cascade\">{$lang['strcascade']}</label></p>" . "\n";
534
            echo "<input type=\"submit\" name=\"drop\" value=\"{$lang['strdrop']}\" />" . "\n";
535
            echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" />" . "\n";
536
            echo '</form>' . "\n";
537
        } else {
538
            $status = $data->dropIndex($_POST['index'], isset($_POST['cascade']));
539
            if (0 == $status) {
540
                $this->doDefault($lang['strindexdropped']);
541
            } else {
542
                $this->doDefault($lang['strindexdroppedbad']);
543
            }
544
        }
545
    }
546
}
547