Issues (217)

src/controllers/TriggersController.php (2 issues)

Labels
Severity
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 TriggersController extends BaseController
15
{
16
    public $controller_title = 'strtables';
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->doTree();
25
        }
26
27
        $this->printHeader($this->headerTitle('', '', $_REQUEST['table'] . ' - ' . $this->lang['strtriggers']));
28
        $this->printBody();
29
30
        switch ($this->action) {
31
            case 'alter':
32
                if (null !== $this->getPostParam('alter')) {
33
                    $this->doSaveAlter();
34
                } else {
35
                    $this->doDefault();
36
                }
37
38
                break;
39
            case 'confirm_alter':
40
                $this->doAlter();
41
42
                break;
43
            case 'confirm_enable':
44
                $this->doEnable(true);
45
46
                break;
47
            case 'confirm_disable':
48
                $this->doDisable(true);
49
50
                break;
51
            case 'save_create':
52
                if (null !== $this->getPostParam('cancel')) {
53
                    $this->doDefault();
54
                } else {
55
                    $this->doSaveCreate();
56
                }
57
58
                break;
59
            case 'create':
60
                $this->doCreate();
61
62
                break;
63
            case 'drop':
64
                if (isset($_POST['yes'])) {
65
                    $this->doDrop(false);
66
                } else {
67
                    $this->doDefault();
68
                }
69
70
                break;
71
            case 'confirm_drop':
72
                $this->doDrop(true);
73
74
                break;
75
            case 'enable':
76
                if (isset($_POST['yes'])) {
77
                    $this->doEnable(false);
78
                } else {
79
                    $this->doDefault();
80
                }
81
82
                break;
83
            case 'disable':
84
                if (isset($_POST['yes'])) {
85
                    $this->doDisable(false);
86
                } else {
87
                    $this->doDefault();
88
                }
89
90
                break;
91
92
            default:
93
                $this->doDefault();
94
95
                break;
96
        }
97
98
        return $this->printFooter();
99
    }
100
101
    /**
102
     * List all the triggers on the table.
103
     *
104
     * @param mixed $msg
105
     */
106
    public function doDefault($msg = ''): void
107
    {
108
        $data = $this->misc->getDatabaseAccessor();
109
110
        $tgPre = static function (&$rowdata, $actions) use ($data) {
111
            // toggle enable/disable trigger per trigger
112
            if (!$data->phpBool($rowdata->fields['tgenabled'])) {
113
                unset($actions['disable']);
114
            } else {
115
                unset($actions['enable']);
116
            }
117
118
            return $actions;
119
        };
120
121
        $this->printTrail('table');
122
        $this->printTabs('table', 'triggers');
123
        $this->printMsg($msg);
124
125
        $triggers = $data->getTriggers($_REQUEST['table']);
126
127
        $columns = [
128
            'trigger' => [
129
                'title' => $this->lang['strname'],
130
                'field' => Decorator::field('tgname'),
131
            ],
132
            'definition' => [
133
                'title' => $this->lang['strdefinition'],
134
                'field' => Decorator::field('tgdef'),
135
            ],
136
            'function' => [
137
                'title' => $this->lang['strfunction'],
138
                'field' => Decorator::field('proproto'),
139
                'url' => "functions?action=properties&amp;server={$_REQUEST['server']}&amp;database={$_REQUEST['database']}&amp;",
140
                'vars' => [
141
                    'schema' => 'pronamespace',
142
                    'function' => 'proproto',
143
                    'function_oid' => 'prooid',
144
                ],
145
            ],
146
            'actions' => [
147
                'title' => $this->lang['stractions'],
148
            ],
149
        ];
150
151
        $actions = [
152
            'alter' => [
153
                'content' => $this->lang['stralter'],
154
                'attr' => [
155
                    'href' => [
156
                        'url' => 'triggers',
157
                        'urlvars' => [
158
                            'action' => 'confirm_alter',
159
                            'table' => $_REQUEST['table'],
160
                            'trigger' => Decorator::field('tgname'),
161
                        ],
162
                    ],
163
                ],
164
            ],
165
            'drop' => [
166
                'content' => $this->lang['strdrop'],
167
                'attr' => [
168
                    'href' => [
169
                        'url' => 'triggers',
170
                        'urlvars' => [
171
                            'action' => 'confirm_drop',
172
                            'table' => $_REQUEST['table'],
173
                            'trigger' => Decorator::field('tgname'),
174
                        ],
175
                    ],
176
                ],
177
            ],
178
        ];
179
180
        if ($data->hasDisableTriggers()) {
181
            $actions['enable'] = [
182
                'content' => $this->lang['strenable'],
183
                'attr' => [
184
                    'href' => [
185
                        'url' => 'triggers',
186
                        'urlvars' => [
187
                            'action' => 'confirm_enable',
188
                            'table' => $_REQUEST['table'],
189
                            'trigger' => Decorator::field('tgname'),
190
                        ],
191
                    ],
192
                ],
193
            ];
194
            $actions['disable'] = [
195
                'content' => $this->lang['strdisable'],
196
                'attr' => [
197
                    'href' => [
198
                        'url' => 'triggers',
199
                        'urlvars' => [
200
                            'action' => 'confirm_disable',
201
                            'table' => $_REQUEST['table'],
202
                            'trigger' => Decorator::field('tgname'),
203
                        ],
204
                    ],
205
                ],
206
            ];
207
        }
208
209
        echo $this->printTable($triggers, $columns, $actions, 'triggers-triggers', $this->lang['strnotriggers'], $tgPre);
0 ignored issues
show
It seems like $triggers can also be of type integer; however, parameter $tabledata of PHPPgAdmin\Controller\BaseController::printTable() does only seem to accept ADORecordSet|PHPPgAdmin\ArrayRecordSet, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

209
        echo $this->printTable(/** @scrutinizer ignore-type */ $triggers, $columns, $actions, 'triggers-triggers', $this->lang['strnotriggers'], $tgPre);
Loading history...
210
211
        $this->printNavLinks(['create' => [
212
            'attr' => [
213
                'href' => [
214
                    'url' => 'triggers',
215
                    'urlvars' => [
216
                        'action' => 'create',
217
                        'server' => $_REQUEST['server'],
218
                        'database' => $_REQUEST['database'],
219
                        'schema' => $_REQUEST['schema'],
220
                        'table' => $_REQUEST['table'],
221
                    ],
222
                ],
223
            ],
224
            'content' => $this->lang['strcreatetrigger'],
225
        ]], 'triggers-triggers', \get_defined_vars());
226
    }
227
228
    public function doTree()
229
    {
230
        $data = $this->misc->getDatabaseAccessor();
231
232
        $triggers = $data->getTriggers($_REQUEST['table']);
233
234
        $attrs = [
235
            'text' => Decorator::field('tgname'),
236
            'icon' => 'Trigger',
237
        ];
238
239
        return $this->printTree($triggers, $attrs, 'triggers');
0 ignored issues
show
It seems like $triggers can also be of type integer; however, parameter $_treedata of PHPPgAdmin\Controller\BaseController::printTree() does only seem to accept PHPPgAdmin\ADORecordSet|PHPPgAdmin\ArrayRecordSet, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

239
        return $this->printTree(/** @scrutinizer ignore-type */ $triggers, $attrs, 'triggers');
Loading history...
240
    }
241
242
    /**
243
     * Function to save after altering a trigger.
244
     */
245
    public function doSaveAlter(): void
246
    {
247
        $data = $this->misc->getDatabaseAccessor();
248
249
        $status = $data->alterTrigger($_POST['table'], $_POST['trigger'], $_POST['name']);
250
251
        if (0 === $status) {
252
            $this->doDefault($this->lang['strtriggeraltered']);
253
        } else {
254
            $this->doAlter($this->lang['strtriggeralteredbad']);
255
        }
256
    }
257
258
    /**
259
     * Function to allow altering of a trigger.
260
     *
261
     * @param mixed $msg
262
     */
263
    public function doAlter($msg = ''): void
264
    {
265
        $data = $this->misc->getDatabaseAccessor();
266
267
        $this->printTrail('trigger');
268
        $this->printTitle($this->lang['stralter'], 'pg.trigger.alter');
269
        $this->printMsg($msg);
270
271
        $triggerdata = $data->getTrigger($_REQUEST['table'], $_REQUEST['trigger']);
272
273
        if (0 < $triggerdata->recordCount()) {
274
            $this->coalesceArr($_POST, 'name', $triggerdata->fields['tgname']);
275
276
            echo '<form action="' . \containerInstance()->subFolder . '/src/views/triggers" method="post">' . \PHP_EOL;
277
            echo '<table>' . \PHP_EOL;
278
            echo "<tr><th class=\"data\">{$this->lang['strname']}</th>" . \PHP_EOL;
279
            echo '<td class="data1">';
280
            echo "<input name=\"name\" size=\"32\" maxlength=\"{$data->_maxNameLen}\" value=\"",
281
            \htmlspecialchars($_POST['name']), '" />' . \PHP_EOL;
282
            echo '</table>' . \PHP_EOL;
283
            echo '<p><input type="hidden" name="action" value="alter" />' . \PHP_EOL;
284
            echo \sprintf('<input type="hidden" name="table" value="%s"  />%s', \htmlspecialchars($_REQUEST['table']), \PHP_EOL);
285
            echo '<input type="hidden" name="trigger" value="', \htmlspecialchars($_REQUEST['trigger']), '" />' . \PHP_EOL;
286
            echo $this->view->form;
287
            echo "<input type=\"submit\" name=\"alter\" value=\"{$this->lang['strok']}\" />" . \PHP_EOL;
288
            echo \sprintf('<input type="submit" name="cancel" value="%s"  /></p>%s', $this->lang['strcancel'], \PHP_EOL);
289
            echo '</form>' . \PHP_EOL;
290
        } else {
291
            echo "<p>{$this->lang['strnodata']}</p>" . \PHP_EOL;
292
        }
293
    }
294
295
    /**
296
     * Show confirmation of drop and perform actual drop.
297
     *
298
     * @param mixed $confirm
299
     */
300
    public function doDrop($confirm): void
301
    {
302
        $data = $this->misc->getDatabaseAccessor();
303
304
        if ($confirm) {
305
            $this->printTrail('trigger');
306
            $this->printTitle($this->lang['strdrop'], 'pg.trigger.drop');
307
308
            echo '<p>', \sprintf(
309
                $this->lang['strconfdroptrigger'],
310
                $this->misc->printVal($_REQUEST['trigger']),
311
                $this->misc->printVal($_REQUEST['table'])
312
            ), '</p>' . \PHP_EOL;
313
314
            echo '<form action="' . \containerInstance()->subFolder . '/src/views/triggers" method="post">' . \PHP_EOL;
315
            echo '<input type="hidden" name="action" value="drop" />' . \PHP_EOL;
316
            echo \sprintf('<input type="hidden" name="table" value="%s"  />%s', \htmlspecialchars($_REQUEST['table']), \PHP_EOL);
317
            echo '<input type="hidden" name="trigger" value="', \htmlspecialchars($_REQUEST['trigger']), '" />' . \PHP_EOL;
318
            echo $this->view->form;
319
            echo "<p><input type=\"checkbox\" id=\"cascade\" name=\"cascade\" /> <label for=\"cascade\">{$this->lang['strcascade']}</label></p>" . \PHP_EOL;
320
            echo "<input type=\"submit\" name=\"yes\" value=\"{$this->lang['stryes']}\" />" . \PHP_EOL;
321
            echo "<input type=\"submit\" name=\"no\" value=\"{$this->lang['strno']}\" />" . \PHP_EOL;
322
            echo '</form>' . \PHP_EOL;
323
        } else {
324
            $status = $data->dropTrigger($_POST['trigger'], $_POST['table'], isset($_POST['cascade']));
325
326
            if (0 === $status) {
327
                $this->doDefault($this->lang['strtriggerdropped']);
328
            } else {
329
                $this->doDefault($this->lang['strtriggerdroppedbad']);
330
            }
331
        }
332
    }
333
334
    /**
335
     * Show confirmation of enable trigger and perform enabling the trigger.
336
     *
337
     * @param mixed $confirm
338
     */
339
    public function doEnable($confirm): void
340
    {
341
        $data = $this->misc->getDatabaseAccessor();
342
343
        if ($confirm) {
344
            $this->printTrail('trigger');
345
            $this->printTitle($this->lang['strenable'], 'pg.table.alter');
346
347
            echo '<p>', \sprintf(
348
                $this->lang['strconfenabletrigger'],
349
                $this->misc->printVal($_REQUEST['trigger']),
350
                $this->misc->printVal($_REQUEST['table'])
351
            ), '</p>' . \PHP_EOL;
352
353
            echo '<form action="' . \containerInstance()->subFolder . '/src/views/triggers" method="post">' . \PHP_EOL;
354
            echo '<input type="hidden" name="action" value="enable" />' . \PHP_EOL;
355
            echo \sprintf('<input type="hidden" name="table" value="%s"  />%s', \htmlspecialchars($_REQUEST['table']), \PHP_EOL);
356
            echo '<input type="hidden" name="trigger" value="', \htmlspecialchars($_REQUEST['trigger']), '" />' . \PHP_EOL;
357
            echo $this->view->form;
358
            echo "<input type=\"submit\" name=\"yes\" value=\"{$this->lang['stryes']}\" />" . \PHP_EOL;
359
            echo "<input type=\"submit\" name=\"no\" value=\"{$this->lang['strno']}\" />" . \PHP_EOL;
360
            echo '</form>' . \PHP_EOL;
361
        } else {
362
            $status = $data->enableTrigger($_POST['trigger'], $_POST['table']);
363
364
            if (0 === $status) {
365
                $this->doDefault($this->lang['strtriggerenabled']);
366
            } else {
367
                $this->doDefault($this->lang['strtriggerenabledbad']);
368
            }
369
        }
370
    }
371
372
    /**
373
     * Show confirmation of disable trigger and perform disabling the trigger.
374
     *
375
     * @param mixed $confirm
376
     */
377
    public function doDisable($confirm): void
378
    {
379
        $data = $this->misc->getDatabaseAccessor();
380
381
        if ($confirm) {
382
            $this->printTrail('trigger');
383
            $this->printTitle($this->lang['strdisable'], 'pg.table.alter');
384
385
            echo '<p>', \sprintf(
386
                $this->lang['strconfdisabletrigger'],
387
                $this->misc->printVal($_REQUEST['trigger']),
388
                $this->misc->printVal($_REQUEST['table'])
389
            ), '</p>' . \PHP_EOL;
390
391
            echo '<form action="' . \containerInstance()->subFolder . '/src/views/triggers" method="post">' . \PHP_EOL;
392
            echo '<input type="hidden" name="action" value="disable" />' . \PHP_EOL;
393
            echo \sprintf('<input type="hidden" name="table" value="%s"  />%s', \htmlspecialchars($_REQUEST['table']), \PHP_EOL);
394
            echo '<input type="hidden" name="trigger" value="', \htmlspecialchars($_REQUEST['trigger']), '" />' . \PHP_EOL;
395
            echo $this->view->form;
396
            echo "<input type=\"submit\" name=\"yes\" value=\"{$this->lang['stryes']}\" />" . \PHP_EOL;
397
            echo "<input type=\"submit\" name=\"no\" value=\"{$this->lang['strno']}\" />" . \PHP_EOL;
398
            echo '</form>' . \PHP_EOL;
399
        } else {
400
            $status = $data->disableTrigger($_POST['trigger'], $_POST['table']);
401
402
            if (0 === $status) {
403
                $this->doDefault($this->lang['strtriggerdisabled']);
404
            } else {
405
                $this->doDefault($this->lang['strtriggerdisabledbad']);
406
            }
407
        }
408
    }
409
410
    /**
411
     * Let them create s.th.
412
     *
413
     * @param mixed $msg
414
     */
415
    public function doCreate($msg = ''): void
416
    {
417
        $data = $this->misc->getDatabaseAccessor();
418
419
        $this->printTrail('table');
420
        $this->printTitle($this->lang['strcreatetrigger'], 'pg.trigger.create');
421
        $this->printMsg($msg);
422
423
        // Get all the functions that can be used in triggers
424
        $funcs = $data->getTriggerFunctions();
425
426
        if (0 === $funcs->recordCount()) {
427
            $this->doDefault($this->lang['strnofunctions']);
428
429
            return;
430
        }
431
432
        // Populate functions
433
        $sel0 = new \PHPPgAdmin\XHtml\XHtmlSelect('formFunction');
434
435
        while (!$funcs->EOF) {
436
            $sel0->add(new \PHPPgAdmin\XHtml\XHtmlOption($funcs->fields['proname']));
437
            $funcs->moveNext();
438
        }
439
440
        // Populate times
441
        $sel1 = new \PHPPgAdmin\XHtml\XHtmlSelect('formExecTime');
442
        $sel1->set_data($data->triggerExecTimes);
443
444
        // Populate events
445
        $sel2 = new \PHPPgAdmin\XHtml\XHtmlSelect('formEvent');
446
        $sel2->set_data($data->triggerEvents);
447
448
        // Populate occurences
449
        $sel3 = new \PHPPgAdmin\XHtml\XHtmlSelect('formFrequency');
450
        $sel3->set_data($data->triggerFrequency);
451
452
        echo '<form action="' . \containerInstance()->subFolder . '/src/views/triggers" method="post">' . \PHP_EOL;
453
        echo '<table>' . \PHP_EOL;
454
        echo '<tr>' . \PHP_EOL;
455
        echo "		<th class=\"data\">{$this->lang['strname']}</th>" . \PHP_EOL;
456
        echo "		<th class=\"data\">{$this->lang['strwhen']}</th>" . \PHP_EOL;
457
        echo '</tr>' . \PHP_EOL;
458
        echo '<tr>' . \PHP_EOL;
459
        echo '		<td class="data1"> <input type="text" name="formTriggerName" size="32" /></td>' . \PHP_EOL;
460
        echo '		<td class="data1"> ', $sel1->fetch(), '</td>' . \PHP_EOL;
461
        echo '</tr>' . \PHP_EOL;
462
        echo '<tr>' . \PHP_EOL;
463
        echo "    <th class=\"data\">{$this->lang['strevent']}</th>" . \PHP_EOL;
464
        echo "    <th class=\"data\">{$this->lang['strforeach']}</th>" . \PHP_EOL;
465
        echo '</tr>' . \PHP_EOL;
466
        echo '<tr>' . \PHP_EOL;
467
        echo '     <td class="data1"> ', $sel2->fetch(), '</td>' . \PHP_EOL;
468
        echo '     <td class="data1"> ', $sel3->fetch(), '</td>' . \PHP_EOL;
469
        echo '</tr>' . \PHP_EOL;
470
        echo "<tr><th class=\"data\"> {$this->lang['strfunction']}</th>" . \PHP_EOL;
471
        echo "<th class=\"data\"> {$this->lang['strarguments']}</th></tr>" . \PHP_EOL;
472
        echo '<tr><td class="data1">', $sel0->fetch(), '</td>' . \PHP_EOL;
473
        echo '<td class="data1">(<input type="text" name="formTriggerArgs" size="32" />)</td>' . \PHP_EOL;
474
        echo '</tr></table>' . \PHP_EOL;
475
        echo "<p><input type=\"submit\" value=\"{$this->lang['strcreate']}\" />" . \PHP_EOL;
476
        echo \sprintf('<input type="submit" name="cancel" value="%s"  /></p>%s', $this->lang['strcancel'], \PHP_EOL);
477
        echo '<input type="hidden" name="action" value="save_create" />' . \PHP_EOL;
478
        echo \sprintf('<input type="hidden" name="table" value="%s"  />%s', \htmlspecialchars($_REQUEST['table']), \PHP_EOL);
479
        echo $this->view->form;
480
        echo '</form>' . \PHP_EOL;
481
    }
482
483
    /**
484
     * Actually creates the new trigger in the database.
485
     */
486
    public function doSaveCreate(): void
487
    {
488
        $data = $this->misc->getDatabaseAccessor();
489
490
        // Check that they've given a name and a definition
491
492
        if ('' === $_POST['formFunction']) {
493
            $this->doCreate($this->lang['strtriggerneedsfunc']);
494
        } elseif ('' === $_POST['formTriggerName']) {
495
            $this->doCreate($this->lang['strtriggerneedsname']);
496
        } elseif ('' === $_POST['formEvent']) {
497
            $this->doCreate();
498
        } else {
499
            $status = $data->createTrigger(
500
                $_POST['formTriggerName'],
501
                $_POST['table'],
502
                $_POST['formFunction'],
503
                $_POST['formExecTime'],
504
                $_POST['formEvent'],
505
                $_POST['formFrequency'],
506
                $_POST['formTriggerArgs']
507
            );
508
509
            if (0 === $status) {
510
                $this->doDefault($this->lang['strtriggercreated']);
511
            } else {
512
                $this->doCreate($this->lang['strtriggercreatedbad']);
513
            }
514
        }
515
    }
516
}
517