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

src/controllers/IndexesController.php (5 issues)

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