Test Failed
Pull Request — develop (#380)
by Felipe
04:40
created

ConstraintsController   F

Complexity

Total Complexity 79

Size/Duplication

Total Lines 870
Duplicated Lines 0 %

Importance

Changes 2
Bugs 1 Features 0
Metric Value
eloc 529
dl 0
loc 870
rs 2.08
c 2
b 1
f 0
wmc 79

10 Methods

Rating   Name   Duplication   Size   Complexity  
B doDefault() 0 120 3
A formDrop() 0 35 1
C render() 0 87 17
B addPrimaryOrUniqueKey() 0 41 11
A doDrop() 0 11 2
A addForeignKey() 0 44 5
C formPrimaryOrUniqueKey() 0 120 12
F _selectFKColumns() 0 185 19
A addCheck() 0 64 4
B formAddForeignKey() 0 88 5

How to fix   Complexity   

Complex Class

Complex classes like ConstraintsController often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use ConstraintsController, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/**
4
 * PHPPgAdmin 6.1.3
5
 */
6
7
namespace PHPPgAdmin\Controller;
8
9
use PHPPgAdmin\Decorators\Decorator;
10
use PHPPgAdmin\Traits\FormTrait;
11
use PHPPgAdmin\XHtml\XHtmlButton;
12
use PHPPgAdmin\XHtml\XHtmlOption;
13
use PHPPgAdmin\XHtml\XHtmlSelect;
14
15
/**
16
 * Base controller class.
17
 */
18
class ConstraintsController extends BaseController
19
{
20
    use FormTrait;
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->/* @scrutinizer ignore-call */doTree();
29
        }
30
31
        $this->printHeader(
32
            $this->lang['strtables'] . ' - ' . $_REQUEST['table'] . ' - ' . $this->lang['strconstraints'],
33
            '<script src="' . \containerInstance()->subFolder . '/assets/js/indexes.js" type="text/javascript"></script>',
34
            true,
35
            'header_select2.twig'
36
        );
37
38
        $onloadInitActions = [
39
            'add_unique_key',
40
            'save_add_unique_key',
41
            'add_primary_key',
42
            'save_add_primary_key',
43
            'add_foreign_key',
44
            'select_referenced_columns',
45
            'save_add_foreign_key',
46
        ];
47
48
        $onloadInit = false;
49
50
        if (\in_array($this->action, $onloadInitActions, true)) {
51
            $onloadInit = true;
52
        }
53
        $this->printBody(true, 'detailbody', $onloadInit);
54
55
        if (isset($_POST['cancel']) || ('drop' === $this->action && !isset($_POST['drop']))) {
56
            $this->action = 'default';
57
        }
58
59
        switch ($this->action) {
60
            case 'add_foreign_key':
61
                $this->formAddForeignKey();
62
63
                break;
64
            case 'select_referenced_columns':
65
                $this->_selectFKColumns();
66
67
                break;
68
            case 'save_add_foreign_key':
69
                $this->addForeignKey();
70
71
                break;
72
            case 'add_unique_key':
73
                $this->formPrimaryOrUniqueKey('unique');
74
75
                break;
76
            case 'add_primary_key':
77
                $this->formPrimaryOrUniqueKey('primary');
78
79
                break;
80
            case 'save_add_unique_key':
81
                $this->addPrimaryOrUniqueKey('unique');
82
83
                break;
84
            case 'save_add_primary_key':
85
                $this->addPrimaryOrUniqueKey('primary');
86
87
                break;
88
            case 'add_check':
89
                $this->addCheck(true);
90
91
                break;
92
            case 'save_add_check':
93
                $this->addCheck(false);
94
95
                break;
96
            case 'drop':
97
                $this->doDrop();
98
99
                break;
100
            case 'confirm_drop':
101
                $this->formDrop();
102
103
                break;
104
105
            default:
106
                $this->doDefault();
107
108
                break;
109
        }
110
111
        $this->printFooter();
112
    }
113
114
    /**
115
     * List all the constraints on the table.
116
     *
117
     * @param mixed $msg
118
     */
119
    public function doDefault($msg = ''): void
120
    {
121
        $data = $this->misc->getDatabaseAccessor();
122
123
        $cnPre = static function (&$rowdata) use ($data): void {
124
            if (null === $rowdata->fields['consrc']) {
125
                $atts = $data->getAttributeNames($_REQUEST['table'], \explode(' ', $rowdata->fields['indkey']));
126
                $rowdata->fields['+definition'] = ('u' === $rowdata->fields['contype'] ? 'UNIQUE (' : 'PRIMARY KEY (') . \implode(',', $atts) . ')';
127
            } else {
128
                $rowdata->fields['+definition'] = $rowdata->fields['consrc'];
129
            }
130
        };
131
132
        $this->printTrail('table');
133
        $this->printTabs('table', 'constraints');
134
        $this->printMsg($msg);
135
136
        $constraints = $data->getConstraints($_REQUEST['table']);
137
138
        $columns = [
139
            'constraint' => [
140
                'title' => $this->lang['strname'],
141
                'field' => Decorator::field('conname'),
142
            ],
143
            'definition' => [
144
                'title' => $this->lang['strdefinition'],
145
                'field' => Decorator::field('+definition'),
146
                'type' => 'pre',
147
            ],
148
            'actions' => [
149
                'title' => $this->lang['stractions'],
150
            ],
151
            'comment' => [
152
                'title' => $this->lang['strcomment'],
153
                'field' => Decorator::field('constcomment'),
154
            ],
155
        ];
156
157
        $actions = [
158
            'drop' => [
159
                'content' => $this->lang['strdrop'],
160
                'attr' => [
161
                    'href' => [
162
                        'url' => 'constraints',
163
                        'urlvars' => [
164
                            'action' => 'confirm_drop',
165
                            'table' => $_REQUEST['table'],
166
                            'constraint' => Decorator::field('conname'),
167
                            'type' => Decorator::field('contype'),
168
                        ],
169
                    ],
170
                ],
171
            ],
172
        ];
173
174
        echo $this->printTable($constraints, $columns, $actions, 'constraints-constraints', $this->lang['strnoconstraints'], $cnPre);
175
176
        $navlinks = [
177
            'addcheck' => [
178
                'attr' => [
179
                    'href' => [
180
                        'url' => 'constraints',
181
                        'urlvars' => [
182
                            'action' => 'add_check',
183
                            'server' => $_REQUEST['server'],
184
                            'database' => $_REQUEST['database'],
185
                            'schema' => $_REQUEST['schema'],
186
                            'table' => $_REQUEST['table'],
187
                        ],
188
                    ],
189
                ],
190
                'content' => $this->lang['straddcheck'],
191
            ],
192
            'adduniq' => [
193
                'attr' => [
194
                    'href' => [
195
                        'url' => 'constraints',
196
                        'urlvars' => [
197
                            'action' => 'add_unique_key',
198
                            'server' => $_REQUEST['server'],
199
                            'database' => $_REQUEST['database'],
200
                            'schema' => $_REQUEST['schema'],
201
                            'table' => $_REQUEST['table'],
202
                        ],
203
                    ],
204
                ],
205
                'content' => $this->lang['stradduniq'],
206
            ],
207
            'addpk' => [
208
                'attr' => [
209
                    'href' => [
210
                        'url' => 'constraints',
211
                        'urlvars' => [
212
                            'action' => 'add_primary_key',
213
                            'server' => $_REQUEST['server'],
214
                            'database' => $_REQUEST['database'],
215
                            'schema' => $_REQUEST['schema'],
216
                            'table' => $_REQUEST['table'],
217
                        ],
218
                    ],
219
                ],
220
                'content' => $this->lang['straddpk'],
221
            ],
222
            'addfk' => [
223
                'attr' => [
224
                    'href' => [
225
                        'url' => 'constraints',
226
                        'urlvars' => [
227
                            'action' => 'add_foreign_key',
228
                            'server' => $_REQUEST['server'],
229
                            'database' => $_REQUEST['database'],
230
                            'schema' => $_REQUEST['schema'],
231
                            'table' => $_REQUEST['table'],
232
                        ],
233
                    ],
234
                ],
235
                'content' => $this->lang['straddfk'],
236
            ],
237
        ];
238
        $this->printNavLinks($navlinks, 'constraints-constraints', \get_defined_vars());
239
    }
240
241
    /**
242
     * Prints the first step to create an FK.
243
     *
244
     * @param string $msg The message
245
     */
246
    public function formAddForeignKey($msg = ''): void
247
    {
248
        $data = $this->misc->getDatabaseAccessor();
249
250
        $this->printTrail('table');
251
        $this->printTitle($this->lang['straddfk'], 'pg.constraint.foreign_key');
252
        $this->printMsg($msg);
253
254
        $attrs = $data->getTableAttributes($_REQUEST['table']);
255
        $tables = $data->getAllTables();
256
257
        $selColumns = new XHtmlSelect('TableColumnList', true, 10);
258
        $selColumns->set_style('width: 15em;');
259
260
        if (0 < $attrs->recordCount()) {
261
            while (!$attrs->EOF) {
262
                $xmloption = new XHtmlOption($attrs->fields['attname']);
263
                $selColumns->add($xmloption);
264
                $attrs->moveNext();
265
            }
266
        }
267
268
        $selIndex = new XHtmlSelect('IndexColumnList[]', true, 10);
269
        $selIndex->set_style('width: 15em;');
270
        $selIndex->set_attribute('id', 'IndexColumnList');
271
        $buttonAdd = new XHtmlButton('add', '>>');
272
        $buttonAdd->set_attribute('onclick', 'buttonPressed(this);');
273
        $buttonAdd->set_attribute('type', 'button');
274
275
        $buttonRemove = new XHtmlButton('remove', '<<');
276
        $buttonRemove->set_attribute('onclick', 'buttonPressed(this);');
277
        $buttonRemove->set_attribute('type', 'button');
278
279
        echo '<form onsubmit="doSelectAll();" name="formIndex" action="constraints" method="post">' . \PHP_EOL;
280
281
        echo '<table>' . \PHP_EOL;
282
        echo \sprintf(
283
            '<tr><th class="data" colspan="3">%s</th></tr>',
284
            $this->lang['strname']
285
        ) . \PHP_EOL;
286
        echo \sprintf(
287
            '<tr><td class="data1" colspan="3"><input type="text" name="name" size="32" maxlength="%s" /></td></tr>',
288
            $data->_maxNameLen
289
        ) . \PHP_EOL;
290
        echo \sprintf(
291
            '<tr><th class="data">%s</th><th class="data">&nbsp;</th><th class="data required">%s</th></tr>',
292
            $this->lang['strtablecolumnlist'],
293
            $this->lang['strfkcolumnlist']
294
        ) . \PHP_EOL;
295
        echo '<tr><td class="data1">' . $selColumns->fetch() . '</td>' . \PHP_EOL;
296
        echo '<td class="data1" style="text-align: center">' . $buttonRemove->fetch() . $buttonAdd->fetch() . '</td>' . \PHP_EOL;
297
        echo '<td class=data1>' . $selIndex->fetch() . '</td></tr>' . \PHP_EOL;
298
        echo \sprintf(
299
            '<tr><th class="data" colspan="3">%s</th></tr>',
300
            $this->lang['strfktarget']
301
        );
302
        echo '<tr>';
303
        echo '<td class="data1" colspan="3"><select class="select2" name="target">';
304
305
        while (!$tables->EOF) {
306
            $key = ['schemaname' => $tables->fields['nspname'], 'tablename' => $tables->fields['relname']];
307
            $key = \serialize($key);
308
            echo '<option value="', \htmlspecialchars($key), '">';
309
310
            if ($tables->fields['nspname'] !== $_REQUEST['schema']) {
311
                echo \htmlspecialchars($tables->fields['nspname']), '.';
312
            }
313
            echo \htmlspecialchars($tables->fields['relname']), '</option>' . \PHP_EOL;
314
            $tables->moveNext();
315
        }
316
        echo '</select>' . \PHP_EOL;
317
        echo '</td></tr>';
318
        echo '</table>' . \PHP_EOL;
319
320
        echo $this->getFormInputsAndButtons(
321
            [
322
                ['name' => 'action', 'type' => 'hidden', 'value' => 'select_referenced_columns'],
323
                ['name' => 'table', 'type' => 'hidden', 'value' => \htmlspecialchars($_REQUEST['table'])],
324
            ],
325
            [
326
                ['type' => 'submit', 'name' => '', 'value' => $this->lang['stradd']],
327
                ['type' => 'submit', 'name' => 'cancel', 'value' => $this->lang['strcancel']],
328
            ]
329
        );
330
331
        echo \sprintf(
332
            '</form>%s',
333
            \PHP_EOL
334
        );
335
    }
336
337
    /**
338
     * Perform actual creation of the FOREIGN KEY constraint.
339
     *
340
     * @param string $msg optional message to display
341
     */
342
    public function addForeignKey($msg = '')
343
    {
344
        $data = $this->misc->getDatabaseAccessor();
345
346
        $this->coalesceArr($_POST, 'name', '');
347
348
        $this->coalesceArr($_POST, 'target', '');
349
350
        $this->coalesceArr($_POST, 'SourceColumnList', 'a:0:{}');
351
352
        $this->coalesceArr($_POST, 'IndexColumnList', []);
353
354
        // Unserialize target
355
        $_POST['target'] = \unserialize($_POST['target']);
356
357
        // Check that they've given at least one column
358
        $temp = \unserialize($_POST['SourceColumnList']);
359
360
        // If IndexColumnList or SourceColumnList are empty, return to screen to select referencing table columns
361
        if (!\is_array($_POST['IndexColumnList'])
362
            || 0 === \count($_POST['IndexColumnList'])
363
            || 0 === \count($temp)) {
364
            return $this->_selectFKColumns($this->lang['strfkneedscols']);
365
        }
366
367
        $status = $data->addForeignKey(
368
            $_POST['table'],
369
            $_POST['target']['schemaname'],
370
            $_POST['target']['tablename'],
371
            \unserialize($_POST['SourceColumnList']),
372
            $_POST['IndexColumnList'],
373
            $_POST['upd_action'],
374
            $_POST['del_action'],
375
            $_POST['match'],
376
            $_POST['deferrable'],
377
            $_POST['initially'],
378
            $_POST['name']
379
        );
380
381
        if (0 === $status) {
382
            return $this->doDefault($this->lang['strfkadded']);
383
        }
384
385
        return $this->_selectFKColumns($this->lang['strfkaddedbad']);
386
    }
387
388
    /**
389
     * Print form to add a PRIMARY KEY or UNIQUE constraint.
390
     *
391
     * @param string $type either primary or unique
392
     * @param string $msg  optional message
393
     */
394
    public function formPrimaryOrUniqueKey($type, $msg = ''): void
395
    {
396
        $data = $this->misc->getDatabaseAccessor();
397
        $this->coalesceArr($_POST, 'name', '');
398
399
        $this->coalesceArr($_POST, 'tablespace', '');
400
401
        $this->printTrail('table');
402
403
        switch ($type) {
404
            case 'primary':
405
                $this->printTitle($this->lang['straddpk'], 'pg.constraint.primary_key');
406
407
                break;
408
            case 'unique':
409
                $this->printTitle($this->lang['stradduniq'], 'pg.constraint.unique_key');
410
411
                break;
412
413
            default:
414
                $this->doDefault($this->lang['strinvalidparam']);
415
416
                return;
417
        }
418
419
        $this->printMsg($msg);
420
421
        $attrs = $data->getTableAttributes($_REQUEST['table']);
422
        $tablespaces = null;
423
        // Fetch all tablespaces from the database
424
        if ($data->hasTablespaces()) {
425
            $tablespaces = $data->getTablespaces();
426
        }
427
428
        $selColumns = new XHtmlSelect('TableColumnList', true, 10);
429
        $selColumns->set_style('width: 15em;');
430
431
        if (0 < $attrs->recordCount()) {
432
            while (!$attrs->EOF) {
433
                $new_option = new XHtmlOption($attrs->fields['attname']);
434
                $selColumns->add($new_option);
435
                $attrs->moveNext();
436
            }
437
        }
438
439
        $selIndex = new XHtmlSelect('IndexColumnList[]', true, 10);
440
        $selIndex->set_style('width: 15em;');
441
        $selIndex->set_attribute('id', 'IndexColumnList');
442
        $buttonAdd = new XHtmlButton('add', '>>');
443
        $buttonAdd->set_attribute('onclick', 'buttonPressed(this);');
444
        $buttonAdd->set_attribute('type', 'button');
445
446
        $buttonRemove = new XHtmlButton('remove', '<<');
447
        $buttonRemove->set_attribute('onclick', 'buttonPressed(this);');
448
        $buttonRemove->set_attribute('type', 'button');
449
450
        echo '<form onsubmit="doSelectAll();" name="formIndex" action="constraints" method="post">' . \PHP_EOL;
451
452
        echo '<table>' . \PHP_EOL;
453
        echo \sprintf(
454
            '<tr><th class="data" colspan="3">%s</th></tr>',
455
            $this->lang['strname']
456
        );
457
        echo '<tr>';
458
        echo '<td class="data1" colspan="3"><input type="text" name="name" value="', \htmlspecialchars($_POST['name']),
459
            \sprintf(
460
                '" size="32" maxlength="%s" /></td></tr>',
461
                $data->_maxNameLen
462
            );
463
        echo \sprintf(
464
            '<tr><th class="data">%s</th><th class="data">&nbsp;</th><th class="data required">%s</th></tr>',
465
            $this->lang['strtablecolumnlist'],
466
            $this->lang['strindexcolumnlist']
467
        ) . \PHP_EOL;
468
        echo '<tr><td class="data1">' . $selColumns->fetch() . '</td>' . \PHP_EOL;
469
        echo '<td class="data1" style="text-align: center">' . $buttonRemove->fetch() . $buttonAdd->fetch() . '</td>';
470
        echo '<td class=data1>' . $selIndex->fetch() . '</td></tr>' . \PHP_EOL;
471
472
        // Tablespace (if there are any)
473
        if ($data->hasTablespaces() && 0 < $tablespaces->recordCount()) {
474
            echo \sprintf(
475
                '<tr><th class="data" colspan="3">%s</th></tr>',
476
                $this->lang['strtablespace']
477
            );
478
            echo '<tr><td class="data1" colspan="3"><select name="tablespace">' . \PHP_EOL;
479
            // Always offer the default (empty) option
480
            echo "\t\t\t\t<option value=\"\"",
481
            ('' === $_POST['tablespace']) ? ' selected="selected"' : '', '></option>' . \PHP_EOL;
482
            // Display all other tablespaces
483
            while (!$tablespaces->EOF) {
484
                $spcname = \htmlspecialchars($tablespaces->fields['spcname']);
485
                echo \sprintf(
486
                    '				<option value="%s"',
487
                    $spcname
488
                ),
489
                ($spcname === $_POST['tablespace']) ? ' selected="selected"' : '', \sprintf(
490
                    '>%s</option>',
491
                    $spcname
492
                ) . \PHP_EOL;
493
                $tablespaces->moveNext();
494
            }
495
            echo '</select></td></tr>' . \PHP_EOL;
496
        }
497
498
        echo '</table>' . \PHP_EOL;
499
500
        echo $this->getFormInputsAndButtons(
501
            [
502
                ['name' => 'action', 'type' => 'hidden', 'value' => ('primary' === $type ? 'save_add_primary_key' : 'save_add_unique_key')],
503
                ['name' => 'table', 'type' => 'hidden', 'value' => \htmlspecialchars($_REQUEST['table'])],
504
            ],
505
            [
506
                ['type' => 'submit', 'name' => '', 'value' => $this->lang['stradd']],
507
                ['type' => 'submit', 'name' => 'cancel', 'value' => $this->lang['strcancel']],
508
            ]
509
        );
510
511
        echo \sprintf(
512
            '</form>%s',
513
            \PHP_EOL
514
        );
515
    }
516
517
    /**
518
     * Try to add a PRIMARY KEY or UNIQUE constraint.
519
     *
520
     * @param string $type either primary or unique
521
     */
522
    public function addPrimaryOrUniqueKey($type)
523
    {
524
        $data = $this->misc->getDatabaseAccessor();
525
526
        $this->coalesceArr($_POST, 'name', '');
527
528
        // Default tablespace to empty if it isn't set
529
        $this->coalesceArr($_POST, 'tablespace', '');
530
531
        if ('primary' === $type) {
532
            // Check that they've given at least one column
533
            if (!isset($_POST['IndexColumnList']) || !\is_array($_POST['IndexColumnList'])
534
                || 0 === \count($_POST['IndexColumnList'])
535
            ) {
536
                $this->formPrimaryOrUniqueKey($type, $this->lang['strpkneedscols']);
537
            } else {
538
                $status = $data->addPrimaryKey($_POST['table'], $_POST['IndexColumnList'], $_POST['name'], $_POST['tablespace']);
539
540
                if (0 === $status) {
541
                    return $this->doDefault($this->lang['strpkadded']);
542
                }
543
544
                return $this->formPrimaryOrUniqueKey($type, $this->lang['strpkaddedbad']);
545
            }
546
        } elseif ('unique' === $type) {
547
            // Check that they've given at least one column
548
            if (!isset($_POST['IndexColumnList']) || !\is_array($_POST['IndexColumnList'])
549
                || 0 === \count($_POST['IndexColumnList'])
550
            ) {
551
                $this->formPrimaryOrUniqueKey($type, $this->lang['struniqneedscols']);
552
            } else {
553
                $status = $data->addUniqueKey($_POST['table'], $_POST['IndexColumnList'], $_POST['name'], $_POST['tablespace']);
554
555
                if (0 === $status) {
556
                    return $this->doDefault($this->lang['struniqadded']);
557
                }
558
559
                return $this->formPrimaryOrUniqueKey($type, $this->lang['struniqaddedbad']);
560
            }
561
        } else {
562
            return $this->doDefault($this->lang['strinvalidparam']);
563
        }
564
    }
565
566
    /**
567
     * Confirm and then actually add a CHECK constraint.
568
     *
569
     * @param mixed $confirm
570
     * @param mixed $msg
571
     */
572
    public function addCheck($confirm, $msg = '')
573
    {
574
        $data = $this->misc->getDatabaseAccessor();
575
576
        $this->coalesceArr($_POST, 'name', '');
577
578
        $this->coalesceArr($_POST, 'definition', '');
579
580
        if ($confirm) {
581
            $this->printTrail('table');
582
            $this->printTitle($this->lang['straddcheck'], 'pg.constraint.check');
583
            $this->printMsg($msg);
584
585
            echo '<form action="' . \containerInstance()->subFolder . '/src/views/constraints" method="post">' . \PHP_EOL;
586
            echo '<table>' . \PHP_EOL;
587
            echo \sprintf(
588
                '<tr><th class="data">%s</th>',
589
                $this->lang['strname']
590
            ) . \PHP_EOL;
591
            echo \sprintf(
592
                '<th class="data required">%s</th></tr>',
593
                $this->lang['strdefinition']
594
            ) . \PHP_EOL;
595
596
            echo \sprintf(
597
                '<tr><td class="data1"><input name="name" size="24" maxlength="%s" value="',
598
                $data->_maxNameLen
599
            ),
600
            \htmlspecialchars($_POST['name']), '" /></td>' . \PHP_EOL;
601
602
            echo '<td class="data1">(<input name="definition" size="64" value="',
603
            \htmlspecialchars($_POST['definition']), '" />)</td></tr>' . \PHP_EOL;
604
            echo '</table>' . \PHP_EOL;
605
606
            echo $this->getFormInputsAndButtons(
607
                [
608
                    ['name' => 'action', 'type' => 'hidden', 'value' => 'save_add_check'],
609
                    ['name' => 'table', 'type' => 'hidden', 'value' => \htmlspecialchars($_REQUEST['table'])],
610
                ],
611
                [
612
                    ['type' => 'submit', 'name' => '', 'value' => $this->lang['stradd']],
613
                    ['type' => 'submit', 'name' => 'cancel', 'value' => $this->lang['strcancel']],
614
                ]
615
            );
616
617
            echo \sprintf(
618
                '</form>%s',
619
                \PHP_EOL
620
            );
621
        } else {
622
            if ('' === \trim($_POST['definition'])) {
623
                $this->addCheck(true, $this->lang['strcheckneedsdefinition']);
624
            } else {
625
                $status = $data->addCheckConstraint(
626
                    $_POST['table'],
627
                    $_POST['definition'],
628
                    $_POST['name']
629
                );
630
631
                if (0 === $status) {
632
                    return $this->doDefault($this->lang['strcheckadded']);
633
                }
634
635
                return $this->addCheck(true, $this->lang['strcheckaddedbad']);
636
            }
637
        }
638
    }
639
640
    /**
641
     * Prints the drop form.
642
     */
643
    public function formDrop(): void
644
    {
645
        $this->printTrail('constraint');
646
        $this->printTitle($this->lang['strdrop'], 'pg.constraint.drop');
647
648
        echo '<p>', \sprintf(
649
            $this->lang['strconfdropconstraint'],
650
            $this->misc->printVal($_REQUEST['constraint']),
651
            $this->misc->printVal($_REQUEST['table'])
652
        ), '</p>' . \PHP_EOL;
653
654
        echo \sprintf(
655
            '<form action="constraints" method="post">%s',
656
            \PHP_EOL
657
        );
658
659
        echo $this->getFormInputsAndButtons(
660
            [
661
                ['name' => 'action', 'value' => 'drop', 'type' => 'hidden'],
662
                ['name' => 'table', 'value' => \htmlspecialchars($_REQUEST['table']), 'type' => 'hidden'],
663
                ['name' => 'constraint', 'value' => \htmlspecialchars($_REQUEST['constraint']), 'type' => 'hidden'],
664
                ['name' => 'type', 'value' => \htmlspecialchars($_REQUEST['type']), 'type' => 'hidden'],
665
            ],
666
            [
667
                ['type' => 'submit', 'name' => 'drop', 'value' => $this->lang['strdrop']],
668
                ['type' => 'submit', 'name' => 'cancel', 'value' => $this->lang['strcancel']],
669
            ],
670
            [
671
                ['type' => 'checkbox', 'name' => 'cascade', 'id' => 'cascade', 'checked' => false, 'labeltext' => $this->lang['strcascade']],
672
            ]
673
        );
674
675
        echo \sprintf(
676
            '</form>%s',
677
            \PHP_EOL
678
        );
679
    }
680
681
    /**
682
     * Try to perform actual drop.
683
     */
684
    public function doDrop()
685
    {
686
        $data = $this->misc->getDatabaseAccessor();
687
688
        $status = $data->dropConstraint($_POST['constraint'], $_POST['table'], $_POST['type'], isset($_POST['cascade']));
689
690
        if (0 === $status) {
691
            return $this->doDefault($this->lang['strconstraintdropped']);
692
        }
693
694
        return $this->doDefault($this->lang['strconstraintdroppedbad']);
695
    }
696
697
    /**
698
     * Prints second screen of FK creation, where you select which columns
699
     * to use in the referencing table.
700
     *
701
     * @param string $msg optional message to display
702
     */
703
    private function _selectFKColumns($msg = '')
704
    {
705
        $data = $this->misc->getDatabaseAccessor();
706
707
        $this->coalesceArr($_POST, 'name', '');
708
709
        $this->coalesceArr($_POST, 'target', '');
710
711
        // Check that they've given at least one source column
712
        if (!isset($_REQUEST['SourceColumnList']) && (!isset($_POST['IndexColumnList']) ||
713
            !\is_array($_POST['IndexColumnList']) ||
714
            0 === \count($_POST['IndexColumnList']))) {
715
            return $this->formAddForeignKey($this->lang['strfkneedscols']);
716
        }
717
        // Copy the IndexColumnList variable from stage 1
718
        if (isset($_REQUEST['IndexColumnList']) && !isset($_REQUEST['SourceColumnList'])) {
719
            $_REQUEST['SourceColumnList'] = \serialize($_REQUEST['IndexColumnList']);
720
        }
721
722
        // Initialise variables
723
        $this->coalesceArr($_POST, 'upd_action', null);
724
725
        $this->coalesceArr($_POST, 'del_action', null);
726
727
        $this->coalesceArr($_POST, 'match', null);
728
729
        $this->coalesceArr($_POST, 'deferrable', null);
730
731
        $this->coalesceArr($_POST, 'initially', null);
732
733
        $_REQUEST['target'] = \unserialize($_REQUEST['target']);
734
735
        $this->printTrail('table');
736
        $this->printTitle($this->lang['straddfk'], 'pg.constraint.foreign_key');
737
        $this->printMsg($msg);
738
739
        // Unserialize target and fetch appropriate table. This is a bit messy
740
        // because the table could be in another schema.
741
        $data->setSchema($_REQUEST['target']['schemaname']);
742
        $attrs = $data->getTableAttributes($_REQUEST['target']['tablename']);
743
        $data->setSchema($_REQUEST['schema']);
744
745
        $selColumns = new XHtmlSelect('TableColumnList', true, 10);
746
        $selColumns->set_style('width: 15em;');
747
748
        if (0 < $attrs->recordCount()) {
749
            while (!$attrs->EOF) {
750
                $xmloption = new XHtmlOption($attrs->fields['attname']);
751
                $selColumns->add($xmloption);
752
                $attrs->moveNext();
753
            }
754
        }
755
756
        $selIndex = new XHtmlSelect('IndexColumnList[]', true, 10);
757
        $selIndex->set_style('width: 15em;');
758
        $selIndex->set_attribute('id', 'IndexColumnList');
759
        $buttonAdd = new XHtmlButton('add', '>>');
760
        $buttonAdd->set_attribute('onclick', 'buttonPressed(this);');
761
        $buttonAdd->set_attribute('type', 'button');
762
763
        $buttonRemove = new XHtmlButton('remove', '<<');
764
        $buttonRemove->set_attribute('onclick', 'buttonPressed(this);');
765
        $buttonRemove->set_attribute('type', 'button');
766
767
        echo '<form onsubmit="doSelectAll();" name="formIndex" action="constraints" method="post">' . \PHP_EOL;
768
769
        echo '<table>' . \PHP_EOL;
770
        echo \sprintf(
771
            '<tr><th class="data" colspan="3">%s</th></tr>',
772
            $this->lang['strfktarget']
773
        );
774
        echo \sprintf(
775
            '<tr><th class="data">%s</th><th class="data">&nbsp;</th><th class=data>%s</th></tr>',
776
            $this->lang['strtablecolumnlist'],
777
            $this->lang['strfkcolumnlist']
778
        ) . \PHP_EOL;
779
        echo '<tr><td class="data1">' . $selColumns->fetch() . '</td>' . \PHP_EOL;
780
        echo '<td class="data1" style="text-align: center">' . $buttonRemove->fetch() . $buttonAdd->fetch() . '</td>';
781
        echo '<td class="data1">' . $selIndex->fetch() . '</td></tr>' . \PHP_EOL;
782
        echo \sprintf(
783
            '<tr><th class="data" colspan="3">%s</th></tr>',
784
            $this->lang['stractions']
785
        );
786
        echo '<tr>';
787
        echo '<td class="data1" colspan="3">' . \PHP_EOL;
788
        // ON SELECT actions
789
        echo \sprintf(
790
            '%s <select name="upd_action">',
791
            $this->lang['stronupdate']
792
        );
793
794
        foreach ($data->fkactions as $v) {
795
            echo \sprintf(
796
                '<option value="%s"',
797
                $v
798
            ), ($_POST['upd_action'] === $v) ? ' selected="selected"' : '', \sprintf(
799
                '>%s</option>',
800
                $v
801
            ) . \PHP_EOL;
802
        }
803
804
        echo '</select><br />' . \PHP_EOL;
805
806
        // ON DELETE actions
807
        echo \sprintf(
808
            '%s <select name="del_action">',
809
            $this->lang['strondelete']
810
        );
811
812
        foreach ($data->fkactions as $v) {
813
            echo \sprintf(
814
                '<option value="%s"',
815
                $v
816
            ), ($_POST['del_action'] === $v) ? ' selected="selected"' : '', \sprintf(
817
                '>%s</option>',
818
                $v
819
            ) . \PHP_EOL;
820
        }
821
822
        echo '</select><br />' . \PHP_EOL;
823
824
        // MATCH options
825
        echo '<select name="match">';
826
827
        foreach ($data->fkmatches as $v) {
828
            echo \sprintf(
829
                '<option value="%s"',
830
                $v
831
            ), ($_POST['match'] === $v) ? ' selected="selected"' : '', \sprintf(
832
                '>%s</option>',
833
                $v
834
            ) . \PHP_EOL;
835
        }
836
837
        echo '</select><br />' . \PHP_EOL;
838
839
        // DEFERRABLE options
840
        echo '<select name="deferrable">';
841
842
        foreach ($data->fkdeferrable as $v) {
843
            echo \sprintf(
844
                '<option value="%s"',
845
                $v
846
            ), ($_POST['deferrable'] === $v) ? ' selected="selected"' : '', \sprintf(
847
                '>%s</option>',
848
                $v
849
            ) . \PHP_EOL;
850
        }
851
852
        echo '</select><br />' . \PHP_EOL;
853
854
        // INITIALLY options
855
        echo '<select name="initially">';
856
857
        foreach ($data->fkinitial as $v) {
858
            echo \sprintf(
859
                '<option value="%s"',
860
                $v
861
            ), ($_POST['initially'] === $v) ? ' selected="selected"' : '', \sprintf(
862
                '>%s</option>',
863
                $v
864
            ) . \PHP_EOL;
865
        }
866
867
        echo '</select>' . \PHP_EOL;
868
        echo '</td></tr>' . \PHP_EOL;
869
        echo '</table>' . \PHP_EOL;
870
871
        echo '<p>';
872
873
        echo '<input type="hidden" name="name" value="', \htmlspecialchars($_REQUEST['name']), '" />' . \PHP_EOL;
874
        echo '<input type="hidden" name="target" value="', \htmlspecialchars(\serialize($_REQUEST['target'])), '" />' . \PHP_EOL;
875
        echo '<input type="hidden" name="SourceColumnList" value="', \htmlspecialchars($_REQUEST['SourceColumnList']), '" />' . \PHP_EOL;
876
877
        echo $this->getActionTableAndButtons(
878
            'save_add_foreign_key',
879
            \htmlspecialchars($_REQUEST['table']),
880
            $this->lang['stradd'],
881
            $this->lang['strcancel']
882
        );
883
884
        echo \sprintf(
885
            '</p>%s</form>%s',
886
            \PHP_EOL,
887
            \PHP_EOL
888
        );
889
    }
890
}
891