Issues (217)

src/controllers/ConstraintsController.php (1 issue)

1
<?php
2
3
/**
4
 * PHPPgAdmin 6.1.3
5
 */
6
7
namespace PHPPgAdmin\Controller;
8
9
use PHPPgAdmin\Decorators\Decorator;
10
11
/**
12
 * Base controller class.
13
 */
14
class ConstraintsController extends BaseController
15
{
16
    use \PHPPgAdmin\Traits\FormTrait;
17
18
    /**
19
     * Default method to render the controller according to the action parameter.
20
     */
21
    public function render()
22
    {
23
        if ('tree' === $this->action) {
24
            return $this->/* @scrutinizer ignore-call */doTree();
25
        }
26
27
        $this->printHeader(
28
            $this->lang['strtables'] . ' - ' . $_REQUEST['table'] . ' - ' . $this->lang['strconstraints'],
29
            '<script src="' . \containerInstance()->subFolder . '/assets/js/indexes.js" type="text/javascript"></script>',
30
            true,
31
            'header_select2.twig'
32
        );
33
34
        $onloadInitActions = [
35
            'add_unique_key',
36
            'save_add_unique_key',
37
            'add_primary_key',
38
            'save_add_primary_key',
39
            'add_foreign_key',
40
            'select_referenced_columns',
41
            'save_add_foreign_key',
42
        ];
43
44
        $onloadInit = false;
45
46
        if (\in_array($this->action, $onloadInitActions, true)) {
47
            $onloadInit = true;
48
        }
49
        $this->printBody(true, 'detailbody', $onloadInit);
50
51
        if (isset($_POST['cancel']) || ('drop' === $this->action && !isset($_POST['drop']))) {
52
            $this->action = 'default';
53
        }
54
55
        switch ($this->action) {
56
            case 'add_foreign_key':
57
                $this->formAddForeignKey();
58
59
                break;
60
            case 'select_referenced_columns':
61
                $this->_selectFKColumns();
62
63
                break;
64
            case 'save_add_foreign_key':
65
                $this->addForeignKey();
66
67
                break;
68
            case 'add_unique_key':
69
                $this->formPrimaryOrUniqueKey('unique');
70
71
                break;
72
            case 'add_primary_key':
73
                $this->formPrimaryOrUniqueKey('primary');
74
75
                break;
76
            case 'save_add_unique_key':
77
                $this->addPrimaryOrUniqueKey('unique');
78
79
                break;
80
            case 'save_add_primary_key':
81
                $this->addPrimaryOrUniqueKey('primary');
82
83
                break;
84
            case 'add_check':
85
                $this->addCheck(true);
86
87
                break;
88
            case 'save_add_check':
89
                $this->addCheck(false);
90
91
                break;
92
            case 'drop':
93
                $this->doDrop();
94
95
                break;
96
            case 'confirm_drop':
97
                $this->formDrop();
98
99
                break;
100
101
            default:
102
                $this->doDefault();
103
104
                break;
105
        }
106
107
        $this->printFooter();
108
    }
109
110
    /**
111
     * List all the constraints on the table.
112
     *
113
     * @param mixed $msg
114
     */
115
    public function doDefault($msg = ''): void
116
    {
117
        $data = $this->misc->getDatabaseAccessor();
118
119
        $cnPre = static function (&$rowdata) use ($data): void {
120
            if (null === $rowdata->fields['consrc']) {
121
                $atts = $data->getAttributeNames($_REQUEST['table'], \explode(' ', $rowdata->fields['indkey']));
122
                $rowdata->fields['+definition'] = ('u' === $rowdata->fields['contype'] ? 'UNIQUE (' : 'PRIMARY KEY (') . \implode(',', $atts) . ')';
123
            } else {
124
                $rowdata->fields['+definition'] = $rowdata->fields['consrc'];
125
            }
126
        };
127
128
        $this->printTrail('table');
129
        $this->printTabs('table', 'constraints');
130
        $this->printMsg($msg);
131
132
        $constraints = $data->getConstraints($_REQUEST['table']);
133
134
        $columns = [
135
            'constraint' => [
136
                'title' => $this->lang['strname'],
137
                'field' => Decorator::field('conname'),
138
            ],
139
            'definition' => [
140
                'title' => $this->lang['strdefinition'],
141
                'field' => Decorator::field('+definition'),
142
                'type' => 'pre',
143
            ],
144
            'actions' => [
145
                'title' => $this->lang['stractions'],
146
            ],
147
            'comment' => [
148
                'title' => $this->lang['strcomment'],
149
                'field' => Decorator::field('constcomment'),
150
            ],
151
        ];
152
153
        $actions = [
154
            'drop' => [
155
                'content' => $this->lang['strdrop'],
156
                'attr' => [
157
                    'href' => [
158
                        'url' => 'constraints',
159
                        'urlvars' => [
160
                            'action' => 'confirm_drop',
161
                            'table' => $_REQUEST['table'],
162
                            'constraint' => Decorator::field('conname'),
163
                            'type' => Decorator::field('contype'),
164
                        ],
165
                    ],
166
                ],
167
            ],
168
        ];
169
170
        echo $this->printTable($constraints, $columns, $actions, 'constraints-constraints', $this->lang['strnoconstraints'], $cnPre);
171
172
        $navlinks = [
173
            'addcheck' => [
174
                'attr' => [
175
                    'href' => [
176
                        'url' => 'constraints',
177
                        'urlvars' => [
178
                            'action' => 'add_check',
179
                            'server' => $_REQUEST['server'],
180
                            'database' => $_REQUEST['database'],
181
                            'schema' => $_REQUEST['schema'],
182
                            'table' => $_REQUEST['table'],
183
                        ],
184
                    ],
185
                ],
186
                'content' => $this->lang['straddcheck'],
187
            ],
188
            'adduniq' => [
189
                'attr' => [
190
                    'href' => [
191
                        'url' => 'constraints',
192
                        'urlvars' => [
193
                            'action' => 'add_unique_key',
194
                            'server' => $_REQUEST['server'],
195
                            'database' => $_REQUEST['database'],
196
                            'schema' => $_REQUEST['schema'],
197
                            'table' => $_REQUEST['table'],
198
                        ],
199
                    ],
200
                ],
201
                'content' => $this->lang['stradduniq'],
202
            ],
203
            'addpk' => [
204
                'attr' => [
205
                    'href' => [
206
                        'url' => 'constraints',
207
                        'urlvars' => [
208
                            'action' => 'add_primary_key',
209
                            'server' => $_REQUEST['server'],
210
                            'database' => $_REQUEST['database'],
211
                            'schema' => $_REQUEST['schema'],
212
                            'table' => $_REQUEST['table'],
213
                        ],
214
                    ],
215
                ],
216
                'content' => $this->lang['straddpk'],
217
            ],
218
            'addfk' => [
219
                'attr' => [
220
                    'href' => [
221
                        'url' => 'constraints',
222
                        'urlvars' => [
223
                            'action' => 'add_foreign_key',
224
                            'server' => $_REQUEST['server'],
225
                            'database' => $_REQUEST['database'],
226
                            'schema' => $_REQUEST['schema'],
227
                            'table' => $_REQUEST['table'],
228
                        ],
229
                    ],
230
                ],
231
                'content' => $this->lang['straddfk'],
232
            ],
233
        ];
234
        $this->printNavLinks($navlinks, 'constraints-constraints', \get_defined_vars());
235
    }
236
237
    /**
238
     * Prints the first step to create an FK.
239
     *
240
     * @param string $msg The message
241
     */
242
    public function formAddForeignKey($msg = ''): void
243
    {
244
        $data = $this->misc->getDatabaseAccessor();
245
246
        $this->printTrail('table');
247
        $this->printTitle($this->lang['straddfk'], 'pg.constraint.foreign_key');
248
        $this->printMsg($msg);
249
250
        $attrs = $data->getTableAttributes($_REQUEST['table']);
251
        $tables = $data->getAllTables();
252
253
        $selColumns = new \PHPPgAdmin\XHtml\XHtmlSelect('TableColumnList', true, 10);
254
        $selColumns->set_style('width: 15em;');
255
256
        if (0 < $attrs->recordCount()) {
257
            while (!$attrs->EOF) {
258
                $xmloption = new \PHPPgAdmin\XHtml\XHtmlOption($attrs->fields['attname']);
259
                $selColumns->add($xmloption);
260
                $attrs->moveNext();
261
            }
262
        }
263
264
        $selIndex = new \PHPPgAdmin\XHtml\XHtmlSelect('IndexColumnList[]', true, 10);
265
        $selIndex->set_style('width: 15em;');
266
        $selIndex->set_attribute('id', 'IndexColumnList');
267
        $buttonAdd = new \PHPPgAdmin\XHtml\XHtmlButton('add', '>>');
268
        $buttonAdd->set_attribute('onclick', 'buttonPressed(this);');
269
        $buttonAdd->set_attribute('type', 'button');
270
271
        $buttonRemove = new \PHPPgAdmin\XHtml\XHtmlButton('remove', '<<');
272
        $buttonRemove->set_attribute('onclick', 'buttonPressed(this);');
273
        $buttonRemove->set_attribute('type', 'button');
274
275
        echo '<form onsubmit="doSelectAll();" name="formIndex" action="constraints" method="post">' . \PHP_EOL;
276
277
        echo '<table>' . \PHP_EOL;
278
        echo "<tr><th class=\"data\" colspan=\"3\">{$this->lang['strname']}</th></tr>" . \PHP_EOL;
279
        echo "<tr><td class=\"data1\" colspan=\"3\"><input type=\"text\" name=\"name\" size=\"32\" maxlength=\"{$data->_maxNameLen}\" /></td></tr>" . \PHP_EOL;
280
        echo "<tr><th class=\"data\">{$this->lang['strtablecolumnlist']}</th><th class=\"data\">&nbsp;</th><th class=\"data required\">{$this->lang['strfkcolumnlist']}</th></tr>" . \PHP_EOL;
281
        echo '<tr><td class="data1">' . $selColumns->fetch() . '</td>' . \PHP_EOL;
282
        echo '<td class="data1" style="text-align: center">' . $buttonRemove->fetch() . $buttonAdd->fetch() . '</td>' . \PHP_EOL;
283
        echo '<td class=data1>' . $selIndex->fetch() . '</td></tr>' . \PHP_EOL;
284
        echo "<tr><th class=\"data\" colspan=\"3\">{$this->lang['strfktarget']}</th></tr>";
285
        echo '<tr>';
286
        echo '<td class="data1" colspan="3"><select class="select2" name="target">';
287
288
        while (!$tables->EOF) {
289
            $key = ['schemaname' => $tables->fields['nspname'], 'tablename' => $tables->fields['relname']];
290
            $key = \serialize($key);
291
            echo '<option value="', \htmlspecialchars($key), '">';
292
293
            if ($tables->fields['nspname'] !== $_REQUEST['schema']) {
294
                echo \htmlspecialchars($tables->fields['nspname']), '.';
295
            }
296
            echo \htmlspecialchars($tables->fields['relname']), '</option>' . \PHP_EOL;
297
            $tables->moveNext();
298
        }
299
        echo '</select>' . \PHP_EOL;
300
        echo '</td></tr>';
301
        echo '</table>' . \PHP_EOL;
302
303
        echo $this->getFormInputsAndButtons(
304
            [
305
                ['name' => 'action', 'type' => 'hidden', 'value' => 'select_referenced_columns'],
306
                ['name' => 'table', 'type' => 'hidden', 'value' => \htmlspecialchars($_REQUEST['table'])],
307
            ],
308
            [
309
                ['type' => 'submit', 'name' => '', 'value' => $this->lang['stradd']],
310
                ['type' => 'submit', 'name' => 'cancel', 'value' => $this->lang['strcancel']],
311
            ]
312
        );
313
314
        echo \sprintf('</form>%s', \PHP_EOL);
315
    }
316
317
    /**
318
     * Perform actual creation of the FOREIGN KEY constraint.
319
     *
320
     * @param string $msg optional message to display
321
     */
322
    public function addForeignKey($msg = '')
323
    {
324
        $data = $this->misc->getDatabaseAccessor();
325
326
        $this->coalesceArr($_POST, 'name', '');
327
328
        $this->coalesceArr($_POST, 'target', '');
329
330
        $this->coalesceArr($_POST, 'SourceColumnList', 'a:0:{}');
331
332
        $this->coalesceArr($_POST, 'IndexColumnList', []);
333
334
        // Unserialize target
335
        $_POST['target'] = \unserialize($_POST['target']);
336
337
        // Check that they've given at least one column
338
        $temp = \unserialize($_POST['SourceColumnList']);
339
340
        // If IndexColumnList or SourceColumnList are empty, return to screen to select referencing table columns
341
        if (!\is_array($_POST['IndexColumnList'])
342
            || 0 === \count($_POST['IndexColumnList'])
343
            || 0 === \count($temp)) {
344
            return $this->_selectFKColumns($this->lang['strfkneedscols']);
345
        }
346
347
        $status = $data->addForeignKey(
348
            $_POST['table'],
349
            $_POST['target']['schemaname'],
350
            $_POST['target']['tablename'],
351
            \unserialize($_POST['SourceColumnList']),
352
            $_POST['IndexColumnList'],
353
            $_POST['upd_action'],
354
            $_POST['del_action'],
355
            $_POST['match'],
356
            $_POST['deferrable'],
357
            $_POST['initially'],
358
            $_POST['name']
359
        );
360
361
        if (0 === $status) {
362
            return $this->doDefault($this->lang['strfkadded']);
363
        }
364
365
        return $this->_selectFKColumns($this->lang['strfkaddedbad']);
366
    }
367
368
    /**
369
     * Print form to add a PRIMARY KEY or UNIQUE constraint.
370
     *
371
     * @param string $type either primary or unique
372
     * @param string $msg  optional message
373
     */
374
    public function formPrimaryOrUniqueKey($type, $msg = ''): void
375
    {
376
        $data = $this->misc->getDatabaseAccessor();
377
        $this->coalesceArr($_POST, 'name', '');
378
379
        $this->coalesceArr($_POST, 'tablespace', '');
380
381
        $this->printTrail('table');
382
383
        switch ($type) {
384
            case 'primary':
385
                $this->printTitle($this->lang['straddpk'], 'pg.constraint.primary_key');
386
387
                break;
388
            case 'unique':
389
                $this->printTitle($this->lang['stradduniq'], 'pg.constraint.unique_key');
390
391
                break;
392
393
            default:
394
                $this->doDefault($this->lang['strinvalidparam']);
395
396
                return;
397
        }
398
399
        $this->printMsg($msg);
400
401
        $attrs = $data->getTableAttributes($_REQUEST['table']);
402
        $tablespaces = null;
403
        // Fetch all tablespaces from the database
404
        if ($data->hasTablespaces()) {
405
            $tablespaces = $data->getTablespaces();
406
        }
407
408
        $selColumns = new \PHPPgAdmin\XHtml\XHtmlSelect('TableColumnList', true, 10);
409
        $selColumns->set_style('width: 15em;');
410
411
        if (0 < $attrs->recordCount()) {
412
            while (!$attrs->EOF) {
413
                $new_option = new \PHPPgAdmin\XHtml\XHtmlOption($attrs->fields['attname']);
414
                $selColumns->add($new_option);
415
                $attrs->moveNext();
416
            }
417
        }
418
419
        $selIndex = new \PHPPgAdmin\XHtml\XHtmlSelect('IndexColumnList[]', true, 10);
420
        $selIndex->set_style('width: 15em;');
421
        $selIndex->set_attribute('id', 'IndexColumnList');
422
        $buttonAdd = new \PHPPgAdmin\XHtml\XHtmlButton('add', '>>');
423
        $buttonAdd->set_attribute('onclick', 'buttonPressed(this);');
424
        $buttonAdd->set_attribute('type', 'button');
425
426
        $buttonRemove = new \PHPPgAdmin\XHtml\XHtmlButton('remove', '<<');
427
        $buttonRemove->set_attribute('onclick', 'buttonPressed(this);');
428
        $buttonRemove->set_attribute('type', 'button');
429
430
        echo '<form onsubmit="doSelectAll();" name="formIndex" action="constraints" method="post">' . \PHP_EOL;
431
432
        echo '<table>' . \PHP_EOL;
433
        echo "<tr><th class=\"data\" colspan=\"3\">{$this->lang['strname']}</th></tr>";
434
        echo '<tr>';
435
        echo '<td class="data1" colspan="3"><input type="text" name="name" value="', \htmlspecialchars($_POST['name']),
436
            "\" size=\"32\" maxlength=\"{$data->_maxNameLen}\" /></td></tr>";
437
        echo "<tr><th class=\"data\">{$this->lang['strtablecolumnlist']}</th><th class=\"data\">&nbsp;</th><th class=\"data required\">{$this->lang['strindexcolumnlist']}</th></tr>" . \PHP_EOL;
0 ignored issues
show
This line exceeds maximum limit of 190 characters; contains 193 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
438
        echo '<tr><td class="data1">' . $selColumns->fetch() . '</td>' . \PHP_EOL;
439
        echo '<td class="data1" style="text-align: center">' . $buttonRemove->fetch() . $buttonAdd->fetch() . '</td>';
440
        echo '<td class=data1>' . $selIndex->fetch() . '</td></tr>' . \PHP_EOL;
441
442
        // Tablespace (if there are any)
443
        if ($data->hasTablespaces() && 0 < $tablespaces->recordCount()) {
444
            echo "<tr><th class=\"data\" colspan=\"3\">{$this->lang['strtablespace']}</th></tr>";
445
            echo '<tr><td class="data1" colspan="3"><select name="tablespace">' . \PHP_EOL;
446
            // Always offer the default (empty) option
447
            echo "\t\t\t\t<option value=\"\"",
448
            ('' === $_POST['tablespace']) ? ' selected="selected"' : '', '></option>' . \PHP_EOL;
449
            // Display all other tablespaces
450
            while (!$tablespaces->EOF) {
451
                $spcname = \htmlspecialchars($tablespaces->fields['spcname']);
452
                echo "\t\t\t\t<option value=\"{$spcname}\"",
453
                ($spcname === $_POST['tablespace']) ? ' selected="selected"' : '', ">{$spcname}</option>" . \PHP_EOL;
454
                $tablespaces->moveNext();
455
            }
456
            echo '</select></td></tr>' . \PHP_EOL;
457
        }
458
459
        echo '</table>' . \PHP_EOL;
460
461
        echo $this->getFormInputsAndButtons(
462
            [
463
                ['name' => 'action', 'type' => 'hidden', 'value' => ('primary' === $type ? 'save_add_primary_key' : 'save_add_unique_key')],
464
                ['name' => 'table', 'type' => 'hidden', 'value' => \htmlspecialchars($_REQUEST['table'])],
465
            ],
466
            [
467
                ['type' => 'submit', 'name' => '', 'value' => $this->lang['stradd']],
468
                ['type' => 'submit', 'name' => 'cancel', 'value' => $this->lang['strcancel']],
469
            ]
470
        );
471
472
        echo \sprintf('</form>%s', \PHP_EOL);
473
    }
474
475
    /**
476
     * Try to add a PRIMARY KEY or UNIQUE constraint.
477
     *
478
     * @param string $type either primary or unique
479
     */
480
    public function addPrimaryOrUniqueKey($type)
481
    {
482
        $data = $this->misc->getDatabaseAccessor();
483
484
        $this->coalesceArr($_POST, 'name', '');
485
486
        // Default tablespace to empty if it isn't set
487
        $this->coalesceArr($_POST, 'tablespace', '');
488
489
        if ('primary' === $type) {
490
            // Check that they've given at least one column
491
            if (!isset($_POST['IndexColumnList']) || !\is_array($_POST['IndexColumnList'])
492
                || 0 === \count($_POST['IndexColumnList'])
493
            ) {
494
                $this->formPrimaryOrUniqueKey($type, $this->lang['strpkneedscols']);
495
            } else {
496
                $status = $data->addPrimaryKey($_POST['table'], $_POST['IndexColumnList'], $_POST['name'], $_POST['tablespace']);
497
498
                if (0 === $status) {
499
                    return $this->doDefault($this->lang['strpkadded']);
500
                }
501
502
                return $this->formPrimaryOrUniqueKey($type, $this->lang['strpkaddedbad']);
503
            }
504
        } elseif ('unique' === $type) {
505
            // Check that they've given at least one column
506
            if (!isset($_POST['IndexColumnList']) || !\is_array($_POST['IndexColumnList'])
507
                || 0 === \count($_POST['IndexColumnList'])
508
            ) {
509
                $this->formPrimaryOrUniqueKey($type, $this->lang['struniqneedscols']);
510
            } else {
511
                $status = $data->addUniqueKey($_POST['table'], $_POST['IndexColumnList'], $_POST['name'], $_POST['tablespace']);
512
513
                if (0 === $status) {
514
                    return $this->doDefault($this->lang['struniqadded']);
515
                }
516
517
                return $this->formPrimaryOrUniqueKey($type, $this->lang['struniqaddedbad']);
518
            }
519
        } else {
520
            return $this->doDefault($this->lang['strinvalidparam']);
521
        }
522
    }
523
524
    /**
525
     * Confirm and then actually add a CHECK constraint.
526
     *
527
     * @param mixed $confirm
528
     * @param mixed $msg
529
     */
530
    public function addCheck($confirm, $msg = '')
531
    {
532
        $data = $this->misc->getDatabaseAccessor();
533
534
        $this->coalesceArr($_POST, 'name', '');
535
536
        $this->coalesceArr($_POST, 'definition', '');
537
538
        if ($confirm) {
539
            $this->printTrail('table');
540
            $this->printTitle($this->lang['straddcheck'], 'pg.constraint.check');
541
            $this->printMsg($msg);
542
543
            echo '<form action="' . \containerInstance()->subFolder . '/src/views/constraints" method="post">' . \PHP_EOL;
544
            echo '<table>' . \PHP_EOL;
545
            echo "<tr><th class=\"data\">{$this->lang['strname']}</th>" . \PHP_EOL;
546
            echo "<th class=\"data required\">{$this->lang['strdefinition']}</th></tr>" . \PHP_EOL;
547
548
            echo "<tr><td class=\"data1\"><input name=\"name\" size=\"24\" maxlength=\"{$data->_maxNameLen}\" value=\"",
549
            \htmlspecialchars($_POST['name']), '" /></td>' . \PHP_EOL;
550
551
            echo '<td class="data1">(<input name="definition" size="64" value="',
552
            \htmlspecialchars($_POST['definition']), '" />)</td></tr>' . \PHP_EOL;
553
            echo '</table>' . \PHP_EOL;
554
555
            echo $this->getFormInputsAndButtons(
556
                [
557
                    ['name' => 'action', 'type' => 'hidden', 'value' => 'save_add_check'],
558
                    ['name' => 'table', 'type' => 'hidden', 'value' => \htmlspecialchars($_REQUEST['table'])],
559
                ],
560
                [
561
                    ['type' => 'submit', 'name' => '', 'value' => $this->lang['stradd']],
562
                    ['type' => 'submit', 'name' => 'cancel', 'value' => $this->lang['strcancel']],
563
                ]
564
            );
565
566
            echo \sprintf('</form>%s', \PHP_EOL);
567
        } else {
568
            if ('' === \trim($_POST['definition'])) {
569
                $this->addCheck(true, $this->lang['strcheckneedsdefinition']);
570
            } else {
571
                $status = $data->addCheckConstraint(
572
                    $_POST['table'],
573
                    $_POST['definition'],
574
                    $_POST['name']
575
                );
576
577
                if (0 === $status) {
578
                    return $this->doDefault($this->lang['strcheckadded']);
579
                }
580
581
                return $this->addCheck(true, $this->lang['strcheckaddedbad']);
582
            }
583
        }
584
    }
585
586
    /**
587
     * Prints the drop form.
588
     */
589
    public function formDrop(): void
590
    {
591
        $this->printTrail('constraint');
592
        $this->printTitle($this->lang['strdrop'], 'pg.constraint.drop');
593
594
        echo '<p>', \sprintf(
595
            $this->lang['strconfdropconstraint'],
596
            $this->misc->printVal($_REQUEST['constraint']),
597
            $this->misc->printVal($_REQUEST['table'])
598
        ), '</p>' . \PHP_EOL;
599
600
        echo \sprintf('<form action="constraints" method="post">%s', \PHP_EOL);
601
602
        echo $this->getFormInputsAndButtons(
603
            [
604
                ['name' => 'action', 'value' => 'drop', 'type' => 'hidden'],
605
                ['name' => 'table', 'value' => \htmlspecialchars($_REQUEST['table']), 'type' => 'hidden'],
606
                ['name' => 'constraint', 'value' => \htmlspecialchars($_REQUEST['constraint']), 'type' => 'hidden'],
607
                ['name' => 'type', 'value' => \htmlspecialchars($_REQUEST['type']), 'type' => 'hidden'],
608
            ],
609
            [
610
                ['type' => 'submit', 'name' => 'drop', 'value' => $this->lang['strdrop']],
611
                ['type' => 'submit', 'name' => 'cancel', 'value' => $this->lang['strcancel']],
612
            ],
613
            [
614
                ['type' => 'checkbox', 'name' => 'cascade', 'id' => 'cascade', 'checked' => false, 'labeltext' => $this->lang['strcascade']],
615
            ]
616
        );
617
618
        echo \sprintf('</form>%s', \PHP_EOL);
619
    }
620
621
    /**
622
     * Try to perform actual drop.
623
     */
624
    public function doDrop()
625
    {
626
        $data = $this->misc->getDatabaseAccessor();
627
628
        $status = $data->dropConstraint($_POST['constraint'], $_POST['table'], $_POST['type'], isset($_POST['cascade']));
629
630
        if (0 === $status) {
631
            return $this->doDefault($this->lang['strconstraintdropped']);
632
        }
633
634
        return $this->doDefault($this->lang['strconstraintdroppedbad']);
635
    }
636
637
    /**
638
     * Prints second screen of FK creation, where you select which columns
639
     * to use in the referencing table.
640
     *
641
     * @param string $msg optional message to display
642
     */
643
    private function _selectFKColumns($msg = '')
644
    {
645
        $data = $this->misc->getDatabaseAccessor();
646
647
        $this->coalesceArr($_POST, 'name', '');
648
649
        $this->coalesceArr($_POST, 'target', '');
650
651
        // Check that they've given at least one source column
652
        if (!isset($_REQUEST['SourceColumnList']) && (!isset($_POST['IndexColumnList']) ||
653
            !\is_array($_POST['IndexColumnList']) ||
654
            0 === \count($_POST['IndexColumnList']))) {
655
            return $this->formAddForeignKey($this->lang['strfkneedscols']);
656
        }
657
        // Copy the IndexColumnList variable from stage 1
658
        if (isset($_REQUEST['IndexColumnList']) && !isset($_REQUEST['SourceColumnList'])) {
659
            $_REQUEST['SourceColumnList'] = \serialize($_REQUEST['IndexColumnList']);
660
        }
661
662
        // Initialise variables
663
        $this->coalesceArr($_POST, 'upd_action', null);
664
665
        $this->coalesceArr($_POST, 'del_action', null);
666
667
        $this->coalesceArr($_POST, 'match', null);
668
669
        $this->coalesceArr($_POST, 'deferrable', null);
670
671
        $this->coalesceArr($_POST, 'initially', null);
672
673
        $_REQUEST['target'] = \unserialize($_REQUEST['target']);
674
675
        $this->printTrail('table');
676
        $this->printTitle($this->lang['straddfk'], 'pg.constraint.foreign_key');
677
        $this->printMsg($msg);
678
679
        // Unserialize target and fetch appropriate table. This is a bit messy
680
        // because the table could be in another schema.
681
        $data->setSchema($_REQUEST['target']['schemaname']);
682
        $attrs = $data->getTableAttributes($_REQUEST['target']['tablename']);
683
        $data->setSchema($_REQUEST['schema']);
684
685
        $selColumns = new \PHPPgAdmin\XHtml\XHtmlSelect('TableColumnList', true, 10);
686
        $selColumns->set_style('width: 15em;');
687
688
        if (0 < $attrs->recordCount()) {
689
            while (!$attrs->EOF) {
690
                $xmloption = new \PHPPgAdmin\XHtml\XHtmlOption($attrs->fields['attname']);
691
                $selColumns->add($xmloption);
692
                $attrs->moveNext();
693
            }
694
        }
695
696
        $selIndex = new \PHPPgAdmin\XHtml\XHtmlSelect('IndexColumnList[]', true, 10);
697
        $selIndex->set_style('width: 15em;');
698
        $selIndex->set_attribute('id', 'IndexColumnList');
699
        $buttonAdd = new \PHPPgAdmin\XHtml\XHtmlButton('add', '>>');
700
        $buttonAdd->set_attribute('onclick', 'buttonPressed(this);');
701
        $buttonAdd->set_attribute('type', 'button');
702
703
        $buttonRemove = new \PHPPgAdmin\XHtml\XHtmlButton('remove', '<<');
704
        $buttonRemove->set_attribute('onclick', 'buttonPressed(this);');
705
        $buttonRemove->set_attribute('type', 'button');
706
707
        echo '<form onsubmit="doSelectAll();" name="formIndex" action="constraints" method="post">' . \PHP_EOL;
708
709
        echo '<table>' . \PHP_EOL;
710
        echo "<tr><th class=\"data\" colspan=\"3\">{$this->lang['strfktarget']}</th></tr>";
711
        echo "<tr><th class=\"data\">{$this->lang['strtablecolumnlist']}</th><th class=\"data\">&nbsp;</th><th class=data>{$this->lang['strfkcolumnlist']}</th></tr>" . \PHP_EOL;
712
        echo '<tr><td class="data1">' . $selColumns->fetch() . '</td>' . \PHP_EOL;
713
        echo '<td class="data1" style="text-align: center">' . $buttonRemove->fetch() . $buttonAdd->fetch() . '</td>';
714
        echo '<td class="data1">' . $selIndex->fetch() . '</td></tr>' . \PHP_EOL;
715
        echo "<tr><th class=\"data\" colspan=\"3\">{$this->lang['stractions']}</th></tr>";
716
        echo '<tr>';
717
        echo '<td class="data1" colspan="3">' . \PHP_EOL;
718
        // ON SELECT actions
719
        echo "{$this->lang['stronupdate']} <select name=\"upd_action\">";
720
721
        foreach ($data->fkactions as $v) {
722
            echo "<option value=\"{$v}\"", ($_POST['upd_action'] === $v) ? ' selected="selected"' : '', ">{$v}</option>" . \PHP_EOL;
723
        }
724
725
        echo '</select><br />' . \PHP_EOL;
726
727
        // ON DELETE actions
728
        echo "{$this->lang['strondelete']} <select name=\"del_action\">";
729
730
        foreach ($data->fkactions as $v) {
731
            echo "<option value=\"{$v}\"", ($_POST['del_action'] === $v) ? ' selected="selected"' : '', ">{$v}</option>" . \PHP_EOL;
732
        }
733
734
        echo '</select><br />' . \PHP_EOL;
735
736
        // MATCH options
737
        echo '<select name="match">';
738
739
        foreach ($data->fkmatches as $v) {
740
            echo "<option value=\"{$v}\"", ($_POST['match'] === $v) ? ' selected="selected"' : '', ">{$v}</option>" . \PHP_EOL;
741
        }
742
743
        echo '</select><br />' . \PHP_EOL;
744
745
        // DEFERRABLE options
746
        echo '<select name="deferrable">';
747
748
        foreach ($data->fkdeferrable as $v) {
749
            echo "<option value=\"{$v}\"", ($_POST['deferrable'] === $v) ? ' selected="selected"' : '', ">{$v}</option>" . \PHP_EOL;
750
        }
751
752
        echo '</select><br />' . \PHP_EOL;
753
754
        // INITIALLY options
755
        echo '<select name="initially">';
756
757
        foreach ($data->fkinitial as $v) {
758
            echo "<option value=\"{$v}\"", ($_POST['initially'] === $v) ? ' selected="selected"' : '', ">{$v}</option>" . \PHP_EOL;
759
        }
760
761
        echo '</select>' . \PHP_EOL;
762
        echo '</td></tr>' . \PHP_EOL;
763
        echo '</table>' . \PHP_EOL;
764
765
        echo '<p>';
766
767
        echo '<input type="hidden" name="name" value="', \htmlspecialchars($_REQUEST['name']), '" />' . \PHP_EOL;
768
        echo '<input type="hidden" name="target" value="', \htmlspecialchars(\serialize($_REQUEST['target'])), '" />' . \PHP_EOL;
769
        echo '<input type="hidden" name="SourceColumnList" value="', \htmlspecialchars($_REQUEST['SourceColumnList']), '" />' . \PHP_EOL;
770
771
        echo $this->getActionTableAndButtons(
772
            'save_add_foreign_key',
773
            \htmlspecialchars($_REQUEST['table']),
774
            $this->lang['stradd'],
775
            $this->lang['strcancel']
776
        );
777
778
        echo \sprintf('</p>%s</form>%s', \PHP_EOL, \PHP_EOL);
779
    }
780
}
781