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

AlldbController::doSaveCreate()   B

Complexity

Conditions 3
Paths 3

Size

Total Lines 34
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 34
rs 8.8571
c 0
b 0
f 0
cc 3
eloc 21
nc 3
nop 0
1
<?php
2
3
/**
4
 * PHPPgAdmin v6.0.0-beta.48
5
 */
6
7
namespace PHPPgAdmin\Controller;
8
9
use PHPPgAdmin\Decorators\Decorator;
10
11
/**
12
 * Base controller class.
13
 *
14
 * @package PHPPgAdmin
15
 */
16
class AlldbController extends BaseController
17
{
18
    use \PHPPgAdmin\Traits\ExportTrait;
19
    public $table_place      = 'alldb-databases';
20
    public $controller_title = 'strdatabases';
21
22
    /**
23
     * Default method to render the controller according to the action parameter.
24
     */
25
    public function render()
26
    {
27
        if ('tree' == $this->action) {
28
            return $this->doTree();
29
        }
30
31
        $header_template = 'header.twig';
32
33
        ob_start();
34
        switch ($this->action) {
35
            case 'export':
36
                $this->doExport();
37
38
                break;
39
            case 'save_create':
40
                if (isset($_POST['cancel'])) {
41
                    $this->doDefault();
42
                } else {
43
                    $this->doSaveCreate();
44
                }
45
46
                break;
47
            case 'create':
48
                $this->doCreate();
49
50
                break;
51
            case 'drop':
52
                if (isset($_REQUEST['drop'])) {
53
                    $this->doDrop(false);
54
                } else {
55
                    $this->doDefault();
56
                }
57
58
                break;
59
            case 'confirm_drop':
60
                $this->doDrop(true);
61
62
                break;
63
            case 'alter':
64
                if (isset($_POST['oldname'], $_POST['newname']) && !isset($_POST['cancel'])) {
65
                    $this->doAlter(false);
66
                } else {
67
                    $this->doDefault();
68
                }
69
70
                break;
71
            case 'confirm_alter':
72
                $this->doAlter(true);
73
74
                break;
75
            default:
76
                $header_template = 'header_datatables.twig';
77
                $this->doDefault();
78
79
                break;
80
        }
81
        $output = ob_get_clean();
82
83
        $this->printHeader($this->headerTitle(), null, true, $header_template);
84
        $this->printBody();
85
        echo $output;
86
87
        return $this->printFooter();
88
    }
89
90
    /**
91
     * Show default list of databases in the server.
92
     *
93
     * @param mixed $msg
94
     */
95
    public function doDefault($msg = '')
96
    {
97
        $this->printTrail('server');
98
        $this->printTabs('server', 'databases');
99
        $this->printMsg($msg);
100
        $data = $this->misc->getDatabaseAccessor();
101
102
        $databases = $data->getDatabases();
103
104
        $this->misc->setReloadBrowser(true);
105
106
        $href = $this->misc->getHREF();
107
108
        $columns = [
109
            'database'   => [
110
                'title' => $this->lang['strdatabase'],
111
                'field' => Decorator::field('datname'),
112
                'url'   => \SUBFOLDER."/redirect/database?{$href}&amp;",
113
                'vars'  => ['database' => 'datname'],
114
            ],
115
            'owner'      => [
116
                'title' => $this->lang['strowner'],
117
                'field' => Decorator::field('datowner'),
118
            ],
119
            'encoding'   => [
120
                'title' => $this->lang['strencoding'],
121
                'field' => Decorator::field('datencoding'),
122
            ],
123
124
            'tablespace' => [
125
                'title' => $this->lang['strtablespace'],
126
                'field' => Decorator::field('tablespace'),
127
            ],
128
            'dbsize'     => [
129
                'title' => $this->lang['strsize'],
130
                'field' => Decorator::field('dbsize'),
131
                'type'  => 'prettysize',
132
            ],
133
            'lc_collate' => [
134
                'title' => $this->lang['strcollation'],
135
                'field' => Decorator::field('datcollate'),
136
            ],
137
            'lc_ctype'   => [
138
                'title' => $this->lang['strctype'],
139
                'field' => Decorator::field('datctype'),
140
            ],
141
            'actions'    => [
142
                'title' => $this->lang['stractions'],
143
            ],
144
            'comment'    => [
145
                'title' => $this->lang['strcomment'],
146
                'field' => Decorator::field('datcomment'),
147
            ],
148
        ];
149
150
        $actions = [
151
            'multiactions' => [
152
                'keycols' => ['database' => 'datname'],
153
                'url'     => 'alldb',
154
                'default' => null,
155
            ],
156
            'drop'         => [
157
                'content'     => $this->lang['strdrop'],
158
                'attr'        => [
159
                    'href' => [
160
                        'url'     => 'alldb',
161
                        'urlvars' => [
162
                            'subject'      => 'database',
163
                            'action'       => 'confirm_drop',
164
                            'dropdatabase' => Decorator::field('datname'),
165
                        ],
166
                    ],
167
                ],
168
                'multiaction' => 'confirm_drop',
169
            ],
170
            'privileges'   => [
171
                'content' => $this->lang['strprivileges'],
172
                'attr'    => [
173
                    'href' => [
174
                        'url'     => 'privileges',
175
                        'urlvars' => [
176
                            'subject'  => 'database',
177
                            'database' => Decorator::field('datname'),
178
                        ],
179
                    ],
180
                ],
181
            ],
182
        ];
183
        if ($data->hasAlterDatabase()) {
184
            $actions['alter'] = [
185
                'content' => $this->lang['stralter'],
186
                'attr'    => [
187
                    'href' => [
188
                        'url'     => 'alldb',
189
                        'urlvars' => [
190
                            'subject'       => 'database',
191
                            'action'        => 'confirm_alter',
192
                            'alterdatabase' => Decorator::field('datname'),
193
                        ],
194
                    ],
195
                ],
196
            ];
197
        }
198
199
        if (!$data->hasTablespaces()) {
200
            unset($columns['tablespace']);
201
        }
202
203
        if (!$data->hasServerAdminFuncs()) {
204
            unset($columns['dbsize']);
205
        }
206
207
        if (!$data->hasDatabaseCollation()) {
208
            unset($columns['lc_collate'], $columns['lc_ctype']);
209
        }
210
211
        if (!isset($data->privlist['database'])) {
212
            unset($actions['privileges']);
213
        }
214
215
        echo $this->printTable($databases, $columns, $actions, $this->table_place, $this->lang['strnodatabases']);
216
217
        $navlinks = [
218
            'create' => [
219
                'attr'    => [
220
                    'href' => [
221
                        'url'     => 'alldb',
222
                        'urlvars' => [
223
                            'action' => 'create',
224
                            'server' => $_REQUEST['server'],
225
                        ],
226
                    ],
227
                ],
228
                'content' => $this->lang['strcreatedatabase'],
229
            ],
230
        ];
231
        $this->printNavLinks($navlinks, $this->table_place, get_defined_vars());
232
    }
233
234
    public function doTree()
235
    {
236
        $data = $this->misc->getDatabaseAccessor();
237
238
        $databases = $data->getDatabases();
239
240
        $reqvars = $this->misc->getRequestVars('database');
241
242
        $attrs = [
243
            'text'    => Decorator::field('datname'),
244
            'icon'    => 'Database',
245
            'toolTip' => Decorator::field('datcomment'),
246
            'action'  => Decorator::redirecturl('redirect', $reqvars, ['subject' => 'database', 'database' => Decorator::field('datname')]),
247
            'branch'  => Decorator::url('/src/views/database', $reqvars, ['action' => 'tree', 'database' => Decorator::field('datname')]),
248
        ];
249
250
        return $this->printTree($databases, $attrs, 'databases');
251
    }
252
253
    /**
254
     * Display a form for alter and perform actual alter.
255
     *
256
     * @param mixed $confirm
257
     */
258
    public function doAlter($confirm)
259
    {
260
        $data = $this->misc->getDatabaseAccessor();
261
262
        if ($confirm) {
263
            $this->printTrail('database');
264
            $this->printTitle($this->lang['stralter'], 'pg.database.alter');
265
266
            echo '<form action="'.\SUBFOLDER.'/src/views/alldb" method="post">'.PHP_EOL;
267
            echo '<table>'.PHP_EOL;
268
            echo "<tr><th class=\"data left required\">{$this->lang['strname']}</th>".PHP_EOL;
269
            echo '<td class="data1">';
270
            echo "<input name=\"newname\" size=\"32\" maxlength=\"{$data->_maxNameLen}\" value=\"",
271
            htmlspecialchars($_REQUEST['alterdatabase']), '" /></td></tr>'.PHP_EOL;
272
273
            if ($data->hasAlterDatabaseOwner() && $data->isSuperUser()) {
274
                // Fetch all users
275
276
                $rs    = $data->getDatabaseOwner($_REQUEST['alterdatabase']);
277
                $owner = isset($rs->fields['usename']) ? $rs->fields['usename'] : '';
278
                $users = $data->getUsers();
279
280
                echo "<tr><th class=\"data left required\">{$this->lang['strowner']}</th>".PHP_EOL;
281
                echo '<td class="data1"><select name="owner">';
282
                while (!$users->EOF) {
283
                    $uname = $users->fields['usename'];
284
                    echo '<option value="', htmlspecialchars($uname), '"',
285
                    ($uname == $owner) ? ' selected="selected"' : '', '>', htmlspecialchars($uname), '</option>'.PHP_EOL;
286
                    $users->moveNext();
287
                }
288
                echo '</select></td></tr>'.PHP_EOL;
289
            }
290
            if ($data->hasSharedComments()) {
291
                $rs      = $data->getDatabaseComment($_REQUEST['alterdatabase']);
292
                $comment = isset($rs->fields['description']) ? $rs->fields['description'] : '';
293
                echo "<tr><th class=\"data left\">{$this->lang['strcomment']}</th>".PHP_EOL;
294
                echo '<td class="data1">';
295
                echo '<textarea rows="3" cols="32" name="dbcomment">',
296
                htmlspecialchars($comment), '</textarea></td></tr>'.PHP_EOL;
297
            }
298
            echo '</table>'.PHP_EOL;
299
            echo '<input type="hidden" name="action" value="alter" />'.PHP_EOL;
300
            echo $this->misc->form;
301
            echo '<input type="hidden" name="oldname" value="',
302
            htmlspecialchars($_REQUEST['alterdatabase']), '" />'.PHP_EOL;
303
            echo "<input type=\"submit\" name=\"alter\" value=\"{$this->lang['stralter']}\" />".PHP_EOL;
304
            echo "<input type=\"submit\" name=\"cancel\" value=\"{$this->lang['strcancel']}\" />".PHP_EOL;
305
            echo '</form>'.PHP_EOL;
306
        } else {
307
            $this->coalesceArr($_POST, 'owner', '');
308
309
            $this->coalesceArr($_POST, 'dbcomment', '');
310
311
            if (0 == $data->alterDatabase($_POST['oldname'], $_POST['newname'], $_POST['owner'], $_POST['dbcomment'])) {
312
                $this->misc->setReloadBrowser(true);
313
                $this->doDefault($this->lang['strdatabasealtered']);
314
            } else {
315
                $this->doDefault($this->lang['strdatabasealteredbad']);
316
            }
317
        }
318
    }
319
320
    /**
321
     * Show confirmation of drop and perform actual drop.
322
     *
323
     * @param mixed $confirm
324
     */
325
    public function doDrop($confirm)
326
    {
327
        $data = $this->misc->getDatabaseAccessor();
328
329
        if (empty($_REQUEST['dropdatabase']) && empty($_REQUEST['ma'])) {
330
            return $this->doDefault($this->lang['strspecifydatabasetodrop']);
331
        }
332
333
        if ($confirm) {
334
            $this->printTrail('database');
335
            $this->printTitle($this->lang['strdrop'], 'pg.database.drop');
336
337
            echo '<form action="'.\SUBFOLDER.'/src/views/alldb" method="post">'.PHP_EOL;
338
            //If multi drop
339
            if (isset($_REQUEST['ma'])) {
340
                foreach ($_REQUEST['ma'] as $v) {
341
                    $a = unserialize(htmlspecialchars_decode($v, ENT_QUOTES));
342
                    echo '<p>', sprintf($this->lang['strconfdropdatabase'], $this->misc->printVal($a['database'])), '</p>'.PHP_EOL;
343
                    printf('<input type="hidden" name="dropdatabase[]" value="%s" />', htmlspecialchars($a['database']));
344
                }
345
            } else {
346
                echo '<p>', sprintf($this->lang['strconfdropdatabase'], $this->misc->printVal($_REQUEST['dropdatabase'])), '</p>'.PHP_EOL;
347
                echo '<input type="hidden" name="dropdatabase" value="', htmlspecialchars($_REQUEST['dropdatabase']), '" />'.PHP_EOL;
348
                // END if multi drop
349
            }
350
351
            echo '<input type="hidden" name="action" value="drop" />'.PHP_EOL;
352
            echo $this->misc->form;
353
            echo "<input type=\"submit\" name=\"drop\" value=\"{$this->lang['strdrop']}\" />".PHP_EOL;
354
            echo "<input type=\"submit\" name=\"cancel\" value=\"{$this->lang['strcancel']}\" />".PHP_EOL;
355
            echo "</form>\n"; //  END confirm
356
        } else {
357
            //If multi drop
358
            if (is_array($_REQUEST['dropdatabase'])) {
359
                $msg = '';
360
                foreach ($_REQUEST['dropdatabase'] as $d) {
361
                    $status = $data->dropDatabase($d);
362
                    if (0 == $status) {
363
                        $msg .= sprintf('%s: %s<br />', htmlentities($d, ENT_QUOTES, 'UTF-8'), $this->lang['strdatabasedropped']);
364
                    } else {
365
                        $this->doDefault(sprintf('%s%s: %s<br />', $msg, htmlentities($d, ENT_QUOTES, 'UTF-8'), $this->lang['strdatabasedroppedbad']));
366
367
                        return;
368
                    }
369
                    // Everything went fine, back to Default page...
370
                }
371
                $this->setReloadDropDatabase(true);
372
                $this->doDefault($msg);
373
            } else {
374
                $status = $data->dropDatabase($_POST['dropdatabase']);
375
                if (0 == $status) {
376
                    $this->setReloadDropDatabase(true);
377
                    $this->doDefault($this->lang['strdatabasedropped']);
378
                } else {
379
                    $this->doDefault($this->lang['strdatabasedroppedbad']);
380
                }
381
            }
382
            //END DROP
383
        }
384
    }
385
386
    // END FUNCTION
387
388
    /**
389
     * Displays a screen where they can enter a new database.
390
     *
391
     * @param mixed $msg
392
     */
393
    public function doCreate($msg = '')
394
    {
395
        $data = $this->misc->getDatabaseAccessor();
396
397
        $this->printTrail('server');
398
        $this->printTitle($this->lang['strcreatedatabase'], 'pg.database.create');
399
        $this->printMsg($msg);
400
401
        $this->coalesceArr($_POST, 'formName', '');
402
403
        // Default encoding is that in language file
404
        $this->coalesceArr($_POST, 'formEncoding', '');
405
        $this->coalesceArr($_POST, 'formTemplate', 'template1');
406
407
        $this->coalesceArr($_POST, 'formSpc', '');
408
409
        $this->coalesceArr($_POST, 'formComment', '');
410
411
        // Fetch a list of databases in the cluster
412
        $templatedbs = $data->getDatabases(false);
413
414
        $tablespaces = null;
415
        // Fetch all tablespaces from the database
416
        if ($data->hasTablespaces()) {
417
            $tablespaces = $data->getTablespaces();
418
        }
419
420
        echo '<form action="'.\SUBFOLDER.'/src/views/alldb" method="post">'.PHP_EOL;
421
        echo '<table>'.PHP_EOL;
422
        echo "\t<tr>\n\t\t<th class=\"data left required\">{$this->lang['strname']}</th>".PHP_EOL;
423
        echo "\t\t<td class=\"data1\"><input name=\"formName\" size=\"32\" maxlength=\"{$data->_maxNameLen}\" value=\"",
424
        htmlspecialchars($_POST['formName']), "\" /></td>\n\t</tr>".PHP_EOL;
425
426
        echo "\t<tr>\n\t\t<th class=\"data left required\">{$this->lang['strtemplatedb']}</th>".PHP_EOL;
427
        echo "\t\t<td class=\"data1\">".PHP_EOL;
428
        echo "\t\t\t<select name=\"formTemplate\">".PHP_EOL;
429
        // Always offer template0 and template1
430
        echo "\t\t\t\t<option value=\"template0\"",
431
        ('template0' == $_POST['formTemplate']) ? ' selected="selected"' : '', '>template0</option>'.PHP_EOL;
432
        echo "\t\t\t\t<option value=\"template1\"",
433
        ('template1' == $_POST['formTemplate']) ? ' selected="selected"' : '', '>template1</option>'.PHP_EOL;
434
        while (!$templatedbs->EOF) {
435
            $dbname = htmlspecialchars($templatedbs->fields['datname']);
436
            if ('template1' != $dbname) {
437
                // filter out for $this->conf[show_system] users so we dont get duplicates
438
                echo "\t\t\t\t<option value=\"{$dbname}\"",
439
                ($dbname == $_POST['formTemplate']) ? ' selected="selected"' : '', ">{$dbname}</option>".PHP_EOL;
440
            }
441
            $templatedbs->moveNext();
442
        }
443
        echo "\t\t\t</select>".PHP_EOL;
444
        echo "\t\t</td>\n\t</tr>".PHP_EOL;
445
446
        // ENCODING
447
        echo "\t<tr>\n\t\t<th class=\"data left required\">{$this->lang['strencoding']}</th>".PHP_EOL;
448
        echo "\t\t<td class=\"data1\">".PHP_EOL;
449
        echo "\t\t\t<select name=\"formEncoding\">".PHP_EOL;
450
        echo "\t\t\t\t<option value=\"\"></option>".PHP_EOL;
451
452
        foreach ($data->codemap as $key) {
453
            echo "\t\t\t\t<option value=\"", htmlspecialchars($key), '"',
454
            ($key == $_POST['formEncoding']) ? ' selected="selected"' : '', '>',
455
            $this->misc->printVal($key), '</option>'.PHP_EOL;
456
        }
457
        echo "\t\t\t</select>".PHP_EOL;
458
        echo "\t\t</td>\n\t</tr>".PHP_EOL;
459
460
        if ($data->hasDatabaseCollation()) {
461
            $this->coalesceArr($_POST, 'formCollate', '');
462
463
            $this->coalesceArr($_POST, 'formCType', '');
464
465
            // LC_COLLATE
466
            echo "\t<tr>\n\t\t<th class=\"data left\">{$this->lang['strcollation']}</th>".PHP_EOL;
467
            echo "\t\t<td class=\"data1\">".PHP_EOL;
468
            echo "\t\t\t<input name=\"formCollate\" value=\"", htmlspecialchars($_POST['formCollate']), '" />'.PHP_EOL;
469
            echo "\t\t</td>\n\t</tr>".PHP_EOL;
470
471
            // LC_CTYPE
472
            echo "\t<tr>\n\t\t<th class=\"data left\">{$this->lang['strctype']}</th>".PHP_EOL;
473
            echo "\t\t<td class=\"data1\">".PHP_EOL;
474
            echo "\t\t\t<input name=\"formCType\" value=\"", htmlspecialchars($_POST['formCType']), '" />'.PHP_EOL;
475
            echo "\t\t</td>\n\t</tr>".PHP_EOL;
476
        }
477
478
        // Tablespace (if there are any)
479
        if ($data->hasTablespaces() && $tablespaces->recordCount() > 0) {
480
            echo "\t<tr>\n\t\t<th class=\"data left\">{$this->lang['strtablespace']}</th>".PHP_EOL;
481
            echo "\t\t<td class=\"data1\">\n\t\t\t<select name=\"formSpc\">".PHP_EOL;
482
            // Always offer the default (empty) option
483
            echo "\t\t\t\t<option value=\"\"",
484
            ('' == $_POST['formSpc']) ? ' selected="selected"' : '', '></option>'.PHP_EOL;
485
            // Display all other tablespaces
486
            while (!$tablespaces->EOF) {
487
                $spcname = htmlspecialchars($tablespaces->fields['spcname']);
488
                echo "\t\t\t\t<option value=\"{$spcname}\"",
489
                ($spcname == $_POST['formSpc']) ? ' selected="selected"' : '', ">{$spcname}</option>".PHP_EOL;
490
                $tablespaces->moveNext();
491
            }
492
            echo "\t\t\t</select>\n\t\t</td>\n\t</tr>".PHP_EOL;
493
        }
494
495
        // Comments (if available)
496
        if ($data->hasSharedComments()) {
497
            echo "\t<tr>\n\t\t<th class=\"data left\">{$this->lang['strcomment']}</th>".PHP_EOL;
498
            echo "\t\t<td><textarea name=\"formComment\" rows=\"3\" cols=\"32\">",
499
            htmlspecialchars($_POST['formComment']), "</textarea></td>\n\t</tr>".PHP_EOL;
500
        }
501
502
        echo '</table>'.PHP_EOL;
503
        echo '<p><input type="hidden" name="action" value="save_create" />'.PHP_EOL;
504
        echo $this->misc->form;
505
        echo "<input type=\"submit\" value=\"{$this->lang['strcreate']}\" />".PHP_EOL;
506
        echo "<input type=\"submit\" name=\"cancel\" value=\"{$this->lang['strcancel']}\" /></p>".PHP_EOL;
507
        echo '</form>'.PHP_EOL;
508
    }
509
510
    /**
511
     * Actually creates the new view in the database.
512
     */
513
    public function doSaveCreate()
514
    {
515
        $data = $this->misc->getDatabaseAccessor();
516
517
        // Default tablespace to null if it isn't set
518
        $this->coalesceArr($_POST, 'formSpc', null);
519
520
        // Default comment to blank if it isn't set
521
        $this->coalesceArr($_POST, 'formComment', null);
522
523
        // Default collate to blank if it isn't set
524
        $this->coalesceArr($_POST, 'formCollate', null);
525
526
        // Default ctype to blank if it isn't set
527
        $this->coalesceArr($_POST, 'formCType', null);
528
529
        // Check that they've given a name and a definition
530
        if ('' == $_POST['formName']) {
531
            $this->doCreate($this->lang['strdatabaseneedsname']);
532
        } else {
533
            $status = $data->createDatabase(
534
                $_POST['formName'],
535
                $_POST['formEncoding'],
536
                $_POST['formSpc'],
537
                $_POST['formComment'],
538
                $_POST['formTemplate'],
539
                $_POST['formCollate'],
540
                $_POST['formCType']
541
            );
542
            if (0 == $status) {
543
                $this->misc->setReloadBrowser(true);
544
                $this->doDefault($this->lang['strdatabasecreated']);
545
            } else {
546
                $this->doCreate($this->lang['strdatabasecreatedbad']);
547
            }
548
        }
549
    }
550
551
    /**
552
     * Displays options for cluster download.
553
     *
554
     * @param mixed $msg
555
     */
556
    public function doExport($msg = '')
557
    {
558
        $this->printTrail('server');
559
        $this->printTabs('server', 'export');
560
        $this->printMsg($msg);
561
562
        $subject = 'server';
563
        $object  = $_REQUEST['server'];
564
565
        $this->prtrace($this->misc->getServerInfo());
566
567
        echo $this->formHeader('dbexport');
568
569
        echo $this->dataOnly(true, true);
570
571
        echo $this->structureOnly();
572
573
        echo $this->structureAndData(true);
574
575
        // dumpall doesn't support gzip
576
        echo $this->displayOrDownload(false);
577
578
        echo $this->formFooter($subject, $object);
579
    }
580
}
581