AdminTrait   F
last analyzed

Complexity

Total Complexity 124

Size/Duplication

Total Lines 996
Duplicated Lines 0 %

Importance

Changes 5
Bugs 2 Features 1
Metric Value
eloc 582
c 5
b 2
f 1
dl 0
loc 996
rs 2
wmc 124

16 Methods

Rating   Name   Duplication   Size   Complexity  
B confirmReindex() 0 49 9
B confirmCluster() 0 44 8
B doCluster() 0 58 10
B doAnalyze() 0 47 9
A doEditAutovacuum() 0 25 3
B doVacuum() 0 49 8
B confirmAnalyze() 0 43 8
C adminActions() 0 76 17
B confirmVacuum() 0 44 8
B doReindex() 0 47 9
A doDropAutovacuum() 0 16 3
A _getReclusterConf() 0 27 4
C confirmEditAutovacuum() 0 96 12
A confirmDropAutovacuum() 0 26 3
C _printAutoVacuumConf() 0 135 9
B doAdmin() 0 83 4

How to fix   Complexity   

Complex Class

Complex classes like AdminTrait 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 AdminTrait, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/**
4
 * PHPPgAdmin 6.1.3
5
 */
6
7
namespace PHPPgAdmin\Traits;
8
9
use PHPPgAdmin\Decorators\Decorator;
10
11
/**
12
 * Common trait for admin features.
13
 */
14
trait AdminTrait
15
{
16
    /**
17
     * Show confirmation of cluster.
18
     *
19
     * @param mixed $type
20
     */
21
    public function confirmCluster($type): void
22
    {
23
        $this->script = ('database' === $type) ? 'database' : 'tables';
24
25
        $script = $this->script;
26
27
        if (('table' === $type) && empty($_REQUEST['table']) && empty($_REQUEST['ma'])) {
28
            $this->doDefault($this->lang['strspecifytabletocluster']);
29
30
            return;
31
        }
32
33
        if (isset($_REQUEST['ma'])) {
34
            $this->printTrail('schema');
35
            $this->printTitle($this->lang['strclusterindex'], 'pg.index.cluster');
36
37
            echo '<form action="' . \containerInstance()->subFolder . "/src/views/{$script}\" method=\"post\">" . \PHP_EOL;
38
39
            foreach ($_REQUEST['ma'] as $v) {
40
                $a = \unserialize(\htmlspecialchars_decode($v, \ENT_QUOTES));
41
                echo '<p>', \sprintf($this->lang['strconfclustertable'], $this->misc->printVal($a['table'])), '</p>' . \PHP_EOL;
42
                echo '<input type="hidden" name="table[]" value="', \htmlspecialchars($a['table']), '" />' . \PHP_EOL;
43
            } //  END if multi cluster
44
        } else {
45
            $this->printTrail($type);
46
            $this->printTitle($this->lang['strclusterindex'], 'pg.index.cluster');
47
48
            echo '<form action="' . \containerInstance()->subFolder . "/src/views/{$script}\" method=\"post\">" . \PHP_EOL;
49
50
            if ('table' === $type) {
51
                echo '<p>', \sprintf($this->lang['strconfclustertable'], $this->misc->printVal($_REQUEST['object'])), '</p>' . \PHP_EOL;
52
                echo '<input type="hidden" name="table" value="', \htmlspecialchars($_REQUEST['object']), '" />' . \PHP_EOL;
53
            } else {
54
                echo '<p>', \sprintf($this->lang['strconfclusterdatabase'], $this->misc->printVal($_REQUEST['object'])), '</p>' . \PHP_EOL;
55
                echo '<input type="hidden" name="table" value="" />' . \PHP_EOL;
56
            }
57
        }
58
        echo '<input type="hidden" name="action" value="cluster" />' . \PHP_EOL;
59
60
        echo $this->view->form;
61
62
        echo "<input type=\"submit\" name=\"cluster\" value=\"{$this->lang['strcluster']}\" />\n"; //TODO
63
        echo "<input type=\"submit\" name=\"cancel\" value=\"{$this->lang['strcancel']}\" />" . \PHP_EOL;
64
        echo "</form>\n"; //  END single cluster
65
    }
66
67
    /**
68
     * Show confirmation of reindex.
69
     *
70
     * @param mixed $type
71
     */
72
    public function confirmReindex($type): void
73
    {
74
        $this->script = ('database' === $type) ? 'database' : 'tables';
75
        $script = $this->script;
76
        $this->misc = $this->misc;
77
        $data = $this->misc->getDatabaseAccessor();
78
79
        if (('table' === $type) && empty($_REQUEST['table']) && empty($_REQUEST['ma'])) {
80
            $this->doDefault($this->lang['strspecifytabletoreindex']);
81
82
            return;
83
        }
84
85
        if (isset($_REQUEST['ma'])) {
86
            $this->printTrail('schema');
87
            $this->printTitle($this->lang['strreindex'], 'pg.reindex');
88
89
            echo '<form action="' . \containerInstance()->subFolder . "/src/views/{$script}\" method=\"post\">" . \PHP_EOL;
90
91
            foreach ($_REQUEST['ma'] as $v) {
92
                $a = \unserialize(\htmlspecialchars_decode($v, \ENT_QUOTES));
93
                echo '<p>', \sprintf($this->lang['strconfreindextable'], $this->misc->printVal($a['table'])), '</p>' . \PHP_EOL;
94
                echo '<input type="hidden" name="table[]" value="', \htmlspecialchars($a['table']), '" />' . \PHP_EOL;
95
            } //  END if multi reindex
96
        } else {
97
            $this->printTrail($type);
98
            $this->printTitle($this->lang['strreindex'], 'pg.reindex');
99
100
            echo '<form action="' . \containerInstance()->subFolder . "/src/views/{$script}\" method=\"post\">" . \PHP_EOL;
101
102
            if ('table' === $type) {
103
                echo '<p>', \sprintf($this->lang['strconfreindextable'], $this->misc->printVal($_REQUEST['object'])), '</p>' . \PHP_EOL;
104
                echo '<input type="hidden" name="table" value="', \htmlspecialchars($_REQUEST['object']), '" />' . \PHP_EOL;
105
            } else {
106
                echo '<p>', \sprintf($this->lang['strconfreindexdatabase'], $this->misc->printVal($_REQUEST['object'])), '</p>' . \PHP_EOL;
107
                echo '<input type="hidden" name="table" value="" />' . \PHP_EOL;
108
            }
109
        }
110
        echo '<input type="hidden" name="action" value="reindex" />' . \PHP_EOL;
111
112
        if ($data->hasForceReindex()) {
113
            echo "<p><input type=\"checkbox\" id=\"reindex_force\" name=\"reindex_force\" /><label for=\"reindex_force\">{$this->lang['strforce']}</label></p>" . \PHP_EOL;
114
        }
115
116
        echo $this->view->form;
117
118
        echo "<input type=\"submit\" name=\"reindex\" value=\"{$this->lang['strreindex']}\" />\n"; //TODO
119
        echo "<input type=\"submit\" name=\"cancel\" value=\"{$this->lang['strcancel']}\" />" . \PHP_EOL;
120
        echo "</form>\n"; //  END single reindex
121
    }
122
123
    /**
124
     * Show confirmation of analyze.
125
     *
126
     * @param mixed $type
127
     */
128
    public function confirmAnalyze($type): void
129
    {
130
        $this->script = ('database' === $type) ? 'database' : 'tables';
131
132
        $script = $this->script;
133
134
        if (('table' === $type) && empty($_REQUEST['table']) && empty($_REQUEST['ma'])) {
135
            $this->doDefault($this->lang['strspecifytabletoanalyze']);
136
137
            return;
138
        }
139
140
        if (isset($_REQUEST['ma'])) {
141
            $this->printTrail('schema');
142
            $this->printTitle($this->lang['stranalyze'], 'pg.analyze');
143
144
            echo '<form action="' . \containerInstance()->subFolder . "/src/views/{$script}\" method=\"post\">" . \PHP_EOL;
145
146
            foreach ($_REQUEST['ma'] as $v) {
147
                $a = \unserialize(\htmlspecialchars_decode($v, \ENT_QUOTES));
148
                echo '<p>', \sprintf($this->lang['strconfanalyzetable'], $this->misc->printVal($a['table'])), '</p>' . \PHP_EOL;
149
                echo '<input type="hidden" name="table[]" value="', \htmlspecialchars($a['table']), '" />' . \PHP_EOL;
150
            } //  END if multi analyze
151
        } else {
152
            $this->printTrail($type);
153
            $this->printTitle($this->lang['stranalyze'], 'pg.analyze');
154
155
            echo '<form action="' . \containerInstance()->subFolder . "/src/views/{$script}\" method=\"post\">" . \PHP_EOL;
156
157
            if ('table' === $type) {
158
                echo '<p>', \sprintf($this->lang['strconfanalyzetable'], $this->misc->printVal($_REQUEST['object'])), '</p>' . \PHP_EOL;
159
                echo '<input type="hidden" name="table" value="', \htmlspecialchars($_REQUEST['object']), '" />' . \PHP_EOL;
160
            } else {
161
                echo '<p>', \sprintf($this->lang['strconfanalyzedatabase'], $this->misc->printVal($_REQUEST['object'])), '</p>' . \PHP_EOL;
162
                echo '<input type="hidden" name="table" value="" />' . \PHP_EOL;
163
            }
164
        }
165
        echo '<input type="hidden" name="action" value="analyze" />' . \PHP_EOL;
166
        echo $this->view->form;
167
168
        echo "<input type=\"submit\" name=\"analyze\" value=\"{$this->lang['stranalyze']}\" />\n"; //TODO
169
        echo "<input type=\"submit\" name=\"cancel\" value=\"{$this->lang['strcancel']}\" />" . \PHP_EOL;
170
        echo "</form>\n"; //  END single analyze
171
    }
172
173
    /**
174
     * Show confirmation of vacuum.
175
     *
176
     * @param mixed $type
177
     */
178
    public function confirmVacuum($type): void
179
    {
180
        $script = ('database' === $type) ? 'database' : 'tables';
181
182
        if (('table' === $type) && empty($_REQUEST['table']) && empty($_REQUEST['ma'])) {
183
            $this->doDefault($this->lang['strspecifytabletovacuum']);
184
185
            return;
186
        }
187
188
        if (isset($_REQUEST['ma'])) {
189
            $this->printTrail('schema');
190
            $this->printTitle($this->lang['strvacuum'], 'pg.vacuum');
191
192
            echo '<form action="' . \containerInstance()->subFolder . "/src/views/{$script}\" method=\"post\">" . \PHP_EOL;
193
194
            foreach ($_REQUEST['ma'] as $v) {
195
                $a = \unserialize(\htmlspecialchars_decode($v, \ENT_QUOTES));
196
                echo '<p>', \sprintf($this->lang['strconfvacuumtable'], $this->misc->printVal($a['table'])), '</p>' . \PHP_EOL;
197
                echo '<input type="hidden" name="table[]" value="', \htmlspecialchars($a['table']), '" />' . \PHP_EOL;
198
            }
199
        } else {
200
            // END if multi vacuum
201
            $this->printTrail($type);
202
            $this->printTitle($this->lang['strvacuum'], 'pg.vacuum');
203
204
            echo '<form action="' . \containerInstance()->subFolder . "/src/views/{$script}\" method=\"post\">" . \PHP_EOL;
205
206
            if ('table' === $type) {
207
                echo '<p>', \sprintf($this->lang['strconfvacuumtable'], $this->misc->printVal($_REQUEST['object'])), '</p>' . \PHP_EOL;
208
                echo '<input type="hidden" name="table" value="', \htmlspecialchars($_REQUEST['object']), '" />' . \PHP_EOL;
209
            } else {
210
                echo '<p>', \sprintf($this->lang['strconfvacuumdatabase'], $this->misc->printVal($_REQUEST['object'])), '</p>' . \PHP_EOL;
211
                echo '<input type="hidden" name="table" value="" />' . \PHP_EOL;
212
            }
213
        }
214
        echo '<input type="hidden" name="action" value="vacuum" />' . \PHP_EOL;
215
        echo $this->view->form;
216
        echo "<p><input type=\"checkbox\" id=\"vacuum_full\" name=\"vacuum_full\" /> <label for=\"vacuum_full\">{$this->lang['strfull']}</label></p>" . \PHP_EOL;
217
        echo "<p><input type=\"checkbox\" id=\"vacuum_analyze\" name=\"vacuum_analyze\" /> <label for=\"vacuum_analyze\">{$this->lang['stranalyze']}</label></p>" . \PHP_EOL;
218
        echo "<p><input type=\"checkbox\" id=\"vacuum_freeze\" name=\"vacuum_freeze\" /> <label for=\"vacuum_freeze\">{$this->lang['strfreeze']}</label></p>" . \PHP_EOL;
219
        echo "<input type=\"submit\" name=\"vacuum\" value=\"{$this->lang['strvacuum']}\" />" . \PHP_EOL;
220
        echo "<input type=\"submit\" name=\"cancel\" value=\"{$this->lang['strcancel']}\" />" . \PHP_EOL;
221
        echo "</form>\n"; //  END single vacuum
222
    }
223
224
    /**
225
     * Add or Edit autovacuum params.
226
     *
227
     * @param mixed $type
228
     * @param mixed $msg
229
     */
230
    public function confirmEditAutovacuum($type, $msg = ''): void
231
    {
232
        $data = $this->misc->getDatabaseAccessor();
233
234
        if (empty($_REQUEST['table'])) {
235
            $this->doAdmin($type, $this->lang['strspecifyeditvacuumtable']);
236
237
            return;
238
        }
239
240
        $script = ('database' === $type) ? 'database' : 'tables';
241
242
        $this->printTrail($type);
243
        $this->printTitle(\sprintf($this->lang['streditvacuumtable'], $this->misc->printVal($_REQUEST['table'])));
244
        $this->printMsg(\sprintf($msg, $this->misc->printVal($_REQUEST['table'])));
245
246
        if (empty($_REQUEST['table'])) {
247
            $this->doAdmin($type, $this->lang['strspecifyeditvacuumtable']);
248
249
            return;
250
        }
251
252
        $old_val = $data->getTableAutovacuum($_REQUEST['table']);
253
        $defaults = $data->getAutovacuum();
254
        $old_val = $old_val->fields;
255
256
        if (isset($old_val['autovacuum_enabled']) && ('off' === $old_val['autovacuum_enabled'])) {
257
            $enabled = '';
258
            $disabled = 'checked="checked"';
259
        } else {
260
            $enabled = 'checked="checked"';
261
            $disabled = '';
262
        }
263
264
        if (!isset($old_val['autovacuum_vacuum_threshold'])) {
265
            $old_val['autovacuum_vacuum_threshold'] = '';
266
        }
267
268
        if (!isset($old_val['autovacuum_vacuum_scale_factor'])) {
269
            $old_val['autovacuum_vacuum_scale_factor'] = '';
270
        }
271
272
        if (!isset($old_val['autovacuum_analyze_threshold'])) {
273
            $old_val['autovacuum_analyze_threshold'] = '';
274
        }
275
276
        if (!isset($old_val['autovacuum_analyze_scale_factor'])) {
277
            $old_val['autovacuum_analyze_scale_factor'] = '';
278
        }
279
280
        if (!isset($old_val['autovacuum_vacuum_cost_delay'])) {
281
            $old_val['autovacuum_vacuum_cost_delay'] = '';
282
        }
283
284
        if (!isset($old_val['autovacuum_vacuum_cost_limit'])) {
285
            $old_val['autovacuum_vacuum_cost_limit'] = '';
286
        }
287
288
        echo '<form action="' . \containerInstance()->subFolder . "/src/views/{$script}\" method=\"post\">" . \PHP_EOL;
289
        echo $this->view->form;
290
        echo '<input type="hidden" name="action" value="editautovac" />' . \PHP_EOL;
291
        echo \sprintf('<input type="hidden" name="table" value="%s"  />%s', \htmlspecialchars($_REQUEST['table']), \PHP_EOL);
292
293
        echo "<br />\n<br />\n<table>" . \PHP_EOL;
294
        echo "\t<tr><td>&nbsp;</td>" . \PHP_EOL;
295
        echo "<th class=\"data\">{$this->lang['strnewvalues']}</th><th class=\"data\">{$this->lang['strdefaultvalues']}</th></tr>" . \PHP_EOL;
296
        echo "\t<tr><th class=\"data left\">{$this->lang['strenable']}</th>" . \PHP_EOL;
297
        echo '<td class="data1">' . \PHP_EOL;
298
        echo "<label for=\"on\">on</label><input type=\"radio\" name=\"autovacuum_enabled\" id=\"on\" value=\"on\" {$enabled} />" . \PHP_EOL;
299
        echo "<label for=\"off\">off</label><input type=\"radio\" name=\"autovacuum_enabled\" id=\"off\" value=\"off\" {$disabled} /></td>" . \PHP_EOL;
300
        echo "<th class=\"data left\">{$defaults['autovacuum']}</th></tr>" . \PHP_EOL;
301
        echo "\t<tr><th class=\"data left\">{$this->lang['strvacuumbasethreshold']}</th>" . \PHP_EOL;
302
        echo "<td class=\"data1\"><input type=\"text\" name=\"autovacuum_vacuum_threshold\" value=\"{$old_val['autovacuum_vacuum_threshold']}\" /></td>" . \PHP_EOL;
303
        echo "<th class=\"data left\">{$defaults['autovacuum_vacuum_threshold']}</th></tr>" . \PHP_EOL;
304
        echo "\t<tr><th class=\"data left\">{$this->lang['strvacuumscalefactor']}</th>" . \PHP_EOL;
305
        echo "<td class=\"data1\"><input type=\"text\" name=\"autovacuum_vacuum_scale_factor\" value=\"{$old_val['autovacuum_vacuum_scale_factor']}\" /></td>" . \PHP_EOL;
306
        echo "<th class=\"data left\">{$defaults['autovacuum_vacuum_scale_factor']}</th></tr>" . \PHP_EOL;
307
        echo "\t<tr><th class=\"data left\">{$this->lang['stranalybasethreshold']}</th>" . \PHP_EOL;
308
        echo "<td class=\"data1\"><input type=\"text\" name=\"autovacuum_analyze_threshold\" value=\"{$old_val['autovacuum_analyze_threshold']}\" /></td>" . \PHP_EOL;
309
        echo "<th class=\"data left\">{$defaults['autovacuum_analyze_threshold']}</th></tr>" . \PHP_EOL;
310
        echo "\t<tr><th class=\"data left\">{$this->lang['stranalyzescalefactor']}</th>" . \PHP_EOL;
311
        echo "<td class=\"data1\"><input type=\"text\" name=\"autovacuum_analyze_scale_factor\" value=\"{$old_val['autovacuum_analyze_scale_factor']}\" /></td>" . \PHP_EOL;
312
        echo "<th class=\"data left\">{$defaults['autovacuum_analyze_scale_factor']}</th></tr>" . \PHP_EOL;
313
        echo "\t<tr><th class=\"data left\">{$this->lang['strvacuumcostdelay']}</th>" . \PHP_EOL;
314
        echo "<td class=\"data1\"><input type=\"text\" name=\"autovacuum_vacuum_cost_delay\" value=\"{$old_val['autovacuum_vacuum_cost_delay']}\" /></td>" . \PHP_EOL;
315
        echo "<th class=\"data left\">{$defaults['autovacuum_vacuum_cost_delay']}</th></tr>" . \PHP_EOL;
316
        echo "\t<tr><th class=\"data left\">{$this->lang['strvacuumcostlimit']}</th>" . \PHP_EOL;
317
        echo "<td class=\"datat1\"><input type=\"text\" name=\"autovacuum_vacuum_cost_limit\" value=\"{$old_val['autovacuum_vacuum_cost_limit']}\" /></td>" . \PHP_EOL;
318
        echo "<th class=\"data left\">{$defaults['autovacuum_vacuum_cost_limit']}</th></tr>" . \PHP_EOL;
319
        echo '</table>' . \PHP_EOL;
320
        echo '<br />';
321
        echo '<br />';
322
        echo "<input type=\"submit\" name=\"save\" value=\"{$this->lang['strsave']}\" />" . \PHP_EOL;
323
        echo \sprintf('<input type="submit" name="cancel" value="%s"  /></p>%s', $this->lang['strcancel'], \PHP_EOL);
324
325
        echo '</form>' . \PHP_EOL;
326
    }
327
328
    /**
329
     * Confirm drop autovacuum params for a table.
330
     *
331
     * @param mixed $type
332
     */
333
    public function confirmDropAutovacuum($type): void
334
    {
335
        $script = ('database' === $type) ? 'database' : 'tables';
336
337
        if (empty($_REQUEST['table'])) {
338
            $this->doAdmin($type, $this->lang['strspecifydelvacuumtable']);
339
340
            return;
341
        }
342
343
        $this->printTrail($type);
344
        $this->printTabs($type, 'admin');
345
346
        \printf(
347
            "<p>{$this->lang['strdelvacuumtable']}</p>\n",
348
            $this->misc->printVal("\"{$_GET['schema']}\".\"{$_GET['table']}\"")
349
        );
350
351
        echo "<form style=\"float: left\" action=\"{$script}\" method=\"post\">" . \PHP_EOL;
352
        echo '<input type="hidden" name="action" value="delautovac" />' . \PHP_EOL;
353
        echo $this->view->form;
354
        echo \sprintf('<input type="hidden" name="table" value="%s"  />%s', \htmlspecialchars($_REQUEST['table']), \PHP_EOL);
355
        echo '<input type="hidden" name="rel" value="', \htmlspecialchars(\serialize([$_REQUEST['schema'], $_REQUEST['table']])), '" />' . \PHP_EOL;
356
        echo "<input type=\"submit\" name=\"yes\" value=\"{$this->lang['stryes']}\" />" . \PHP_EOL;
357
        echo "<input type=\"submit\" name=\"cancel\" value=\"{$this->lang['strcancel']}\" />" . \PHP_EOL;
358
        echo '</form>' . \PHP_EOL;
359
    }
360
361
    /**
362
     * perform cluster.
363
     *
364
     * @param mixed $type
365
     */
366
    public function doCluster($type): void
367
    {
368
        $data = $this->misc->getDatabaseAccessor();
369
370
        if (('table' === $type) && empty($_REQUEST['table']) && empty($_REQUEST['ma'])) {
371
            $this->doDefault($this->lang['strspecifytabletocluster']);
372
373
            return;
374
        }
375
376
        $msg = '';
377
        //If multi table cluster
378
        if ('table' === $type) {
379
            // cluster one or more table
380
            if (\is_array($_REQUEST['table'])) {
381
                foreach ($_REQUEST['table'] as $o) {
382
                    [$status, $sql] = $data->clusterIndex($o);
383
                    $msg .= \sprintf('%s<br />', $sql);
384
385
                    if (0 === $status) {
386
                        $msg .= \sprintf(
387
                            '%s: %s<br />',
388
                            \htmlentities($o, \ENT_QUOTES, 'UTF-8'),
389
                            $this->lang['strclusteredgood']
390
                        );
391
                    } else {
392
                        $this->doDefault(\sprintf(
393
                            '%s %s%s: %s<br />',
394
                            $type,
395
                            $msg,
396
                            \htmlentities($o, \ENT_QUOTES, 'UTF-8'),
397
                            $this->lang['strclusteredbad']
398
                        ));
399
400
                        return;
401
                    }
402
                }
403
                // Everything went fine, back to the Default page....
404
                $this->doDefault($msg);
405
            } else {
406
                [$status, $sql] = $data->clusterIndex($_REQUEST['object']);
407
                $msg .= \sprintf('%s<br />', $sql);
408
409
                if (0 === $status) {
410
                    $this->doAdmin($type, $msg . $this->lang['strclusteredgood']);
411
                } else {
412
                    $this->doAdmin($type, $msg . $this->lang['strclusteredbad']);
413
                }
414
            }
415
        } else {
416
            // Cluster all tables in database
417
            [$status, $sql] = $data->clusterIndex();
418
            $msg .= \sprintf('%s<br />', $sql);
419
420
            if (0 === $status) {
421
                $this->doAdmin($type, $msg . $this->lang['strclusteredgood']);
422
            } else {
423
                $this->doAdmin($type, $msg . $this->lang['strclusteredbad']);
424
            }
425
        }
426
    }
427
428
    /**
429
     * perform reindex.
430
     *
431
     * @param mixed $type
432
     */
433
    public function doReindex($type): void
434
    {
435
        $this->misc = $this->misc;
436
        $data = $this->misc->getDatabaseAccessor();
437
438
        if (('table' === $type) && empty($_REQUEST['table']) && empty($_REQUEST['ma'])) {
439
            $this->doDefault($this->lang['strspecifytabletoreindex']);
440
441
            return;
442
        }
443
444
        //If multi table reindex
445
        if (('table' === $type) && \is_array($_REQUEST['table'])) {
446
            $msg = '';
447
448
            foreach ($_REQUEST['table'] as $o) {
449
                $status = $data->reindex(\mb_strtoupper($type), $o, isset($_REQUEST['reindex_force']));
450
451
                if (0 === $status) {
452
                    $msg .= \sprintf(
453
                        '%s: %s<br />',
454
                        \htmlentities($o, \ENT_QUOTES, 'UTF-8'),
455
                        $this->lang['strreindexgood']
456
                    );
457
                } else {
458
                    $this->doDefault(\sprintf(
459
                        '%s %s%s: %s<br />',
460
                        $type,
461
                        $msg,
462
                        \htmlentities($o, \ENT_QUOTES, 'UTF-8'),
463
                        $this->lang['strreindexbad']
464
                    ));
465
466
                    return;
467
                }
468
            }
469
            // Everything went fine, back to the Default page....
470
            $this->view->setReloadBrowser(true);
471
            $this->doDefault($msg);
472
        } else {
473
            $status = $data->reindex(\mb_strtoupper($type), $_REQUEST['object'], isset($_REQUEST['reindex_force']));
474
475
            if (0 === $status) {
476
                $this->view->setReloadBrowser(true);
477
                $this->doAdmin($type, $this->lang['strreindexgood']);
478
            } else {
479
                $this->doAdmin($type, $this->lang['strreindexbad']);
480
            }
481
        }
482
    }
483
484
    /**
485
     * perform analyze.
486
     *
487
     * @param mixed $type
488
     */
489
    public function doAnalyze($type): void
490
    {
491
        $data = $this->misc->getDatabaseAccessor();
492
493
        if (('table' === $type) && empty($_REQUEST['table']) && empty($_REQUEST['ma'])) {
494
            $this->doDefault($this->lang['strspecifytabletoanalyze']);
495
496
            return;
497
        }
498
499
        //If multi table analyze
500
        if (('table' === $type) && \is_array($_REQUEST['table'])) {
501
            $msg = '';
502
503
            foreach ($_REQUEST['table'] as $o) {
504
                $status = $data->analyzeDB($o);
505
506
                if (0 === $status) {
507
                    $msg .= \sprintf(
508
                        '%s: %s<br />',
509
                        \htmlentities($o, \ENT_QUOTES, 'UTF-8'),
510
                        $this->lang['stranalyzegood']
511
                    );
512
                } else {
513
                    $this->doDefault(\sprintf(
514
                        '%s %s%s: %s<br />',
515
                        $type,
516
                        $msg,
517
                        \htmlentities($o, \ENT_QUOTES, 'UTF-8'),
518
                        $this->lang['stranalyzebad']
519
                    ));
520
521
                    return;
522
                }
523
            }
524
            // Everything went fine, back to the Default page....
525
            $this->view->setReloadBrowser(true);
526
            $this->doDefault($msg);
527
        } else {
528
            //we must pass table here. When empty, analyze the whole db
529
            $status = $data->analyzeDB($_REQUEST['table']);
530
531
            if (0 === $status) {
532
                $this->view->setReloadBrowser(true);
533
                $this->doAdmin($type, $this->lang['stranalyzegood']);
534
            } else {
535
                $this->doAdmin($type, $this->lang['stranalyzebad']);
536
            }
537
        }
538
    }
539
540
    /**
541
     * perform actual vacuum.
542
     *
543
     * @param mixed $type
544
     */
545
    public function doVacuum($type)
546
    {
547
        $data = $this->misc->getDatabaseAccessor();
548
549
        if (('table' === $type) && empty($_REQUEST['table']) && empty($_REQUEST['ma'])) {
550
            $this->doDefault($this->lang['strspecifytabletovacuum']);
551
552
            return;
553
        }
554
555
        //If multi drop
556
        if (\is_array($_REQUEST['table'])) {
557
            $msg = '';
558
559
            foreach ($_REQUEST['table'] as $t) {
560
                [$status, $sql] = $data->vacuumDB($t, isset($_REQUEST['vacuum_analyze']), isset($_REQUEST['vacuum_full']), isset($_REQUEST['vacuum_freeze']));
561
562
                if (0 !== $status) {
563
                    return $this->doDefault(\sprintf(
564
                        '%s %s%s: %s<br />',
565
                        $type,
566
                        $msg,
567
                        \htmlentities($t, \ENT_QUOTES, 'UTF-8'),
568
                        $this->lang['strvacuumbad']
569
                    ));
570
                }
571
                $msg .= \sprintf(
572
                    '%s%s %s: %s<br />',
573
                    $sql,
574
                    \PHP_EOL,
575
                    \htmlentities($t, \ENT_QUOTES, 'UTF-8'),
576
                    $this->lang['strvacuumgood']
577
                );
578
            }
579
            // Everything went fine, back to the Default page....
580
            $this->view->setReloadBrowser(true);
581
582
            return $this->doDefault($msg);
583
        }
584
        //we must pass table here. When empty, vacuum the whole db
585
        [$status, $sql] = $data->vacuumDB($_REQUEST['table'], isset($_REQUEST['vacuum_analyze']), isset($_REQUEST['vacuum_full']), isset($_REQUEST['vacuum_freeze']));
586
587
        if (0 === $status) {
588
            $this->view->setReloadBrowser(true);
589
590
            return $this->doAdmin($type, \sprintf('%s%s%s', $sql, \PHP_EOL, $this->lang['strvacuumgood']));
591
        }
592
593
        return $this->doAdmin($type, $this->lang['strvacuumbad']);
594
    }
595
596
    /**
597
     * persist changes in autovacuum settings.
598
     *
599
     * @param mixed $type
600
     * @param mixed $confirm
601
     * @param mixed $msg
602
     */
603
    public function doEditAutovacuum($type): void
604
    {
605
        $data = $this->misc->getDatabaseAccessor();
606
607
        if (empty($_REQUEST['table'])) {
608
            $this->doAdmin($type, $this->lang['strspecifyeditvacuumtable']);
609
610
            return;
611
        }
612
613
        $status = $data->saveAutovacuum(
614
            $_REQUEST['table'],
615
            $_POST['autovacuum_enabled'],
616
            $_POST['autovacuum_vacuum_threshold'],
617
            $_POST['autovacuum_vacuum_scale_factor'],
618
            $_POST['autovacuum_analyze_threshold'],
619
            $_POST['autovacuum_analyze_scale_factor'],
620
            $_POST['autovacuum_vacuum_cost_delay'],
621
            $_POST['autovacuum_vacuum_cost_limit']
622
        );
623
624
        if (0 === $status) {
625
            $this->doAdmin($type, \sprintf($this->lang['strsetvacuumtablesaved'], $_REQUEST['table']));
626
        } else {
627
            $this->confirmEditAutovacuum($type, $this->lang['strsetvacuumtablefail']);
628
        }
629
    }
630
631
    /**
632
     * drop autovacuum settings.
633
     *
634
     * @param mixed $type
635
     */
636
    public function doDropAutovacuum($type): void
637
    {
638
        $data = $this->misc->getDatabaseAccessor();
639
640
        if (empty($_REQUEST['table'])) {
641
            $this->doAdmin($type, $this->lang['strspecifydelvacuumtable']);
642
643
            return;
644
        }
645
646
        $status = $data->dropAutovacuum($_POST['table']);
647
648
        if (0 === $status) {
649
            $this->doAdmin($type, \sprintf($this->lang['strvacuumtablereset'], $this->misc->printVal($_POST['table'])));
650
        } else {
651
            $this->doAdmin($type, \sprintf($this->lang['strdelvacuumtablefail'], $this->misc->printVal($_POST['table'])));
652
        }
653
    }
654
655
    /**
656
     * Database/table administration and tuning tasks.
657
     *
658
     * Release: admin
659
     *
660
     * @param mixed $type
661
     * @param mixed $msg
662
     */
663
    public function doAdmin($type, $msg = ''): void
664
    {
665
        $this->script = ('database' === $type) ? 'database' : 'tables';
666
667
        $script = $this->script;
668
669
        $data = $this->misc->getDatabaseAccessor();
670
671
        $this->printTrail($type);
672
        $this->printTabs($type, 'admin');
673
        $this->printMsg($msg);
674
675
        if ('database' === $type) {
676
            \printf("<p>{$this->lang['stradminondatabase']}</p>\n", $this->misc->printVal($_REQUEST['object']));
677
        } else {
678
            \printf("<p>{$this->lang['stradminontable']}</p>\n", $this->misc->printVal($_REQUEST['object']));
679
        }
680
681
        echo '<table style="width: 50%">' . \PHP_EOL;
682
        echo '<tr>' . \PHP_EOL;
683
        echo '<th class="data">';
684
        $this->view->printHelp($this->lang['strvacuum'], 'pg.admin.vacuum') . '</th>' . \PHP_EOL;
685
        echo '</th>';
686
        echo '<th class="data">';
687
        $this->view->printHelp($this->lang['stranalyze'], 'pg.admin.analyze');
688
        echo '</th>';
689
690
        $table_hidden_inputs = ('table' === $type) ?
691
        \sprintf(
692
            '<input type="hidden" name="table" value="%s" />%s<input type="hidden" name="subject" value="table" />%s',
693
            \htmlspecialchars($_REQUEST['object']),
694
            \PHP_EOL,
695
            \PHP_EOL
696
        ) : '';
697
698
        [$recluster_help, $reclusterconf] = $this->_getReclusterConf($data, $type, $table_hidden_inputs);
699
700
        echo $recluster_help;
701
702
        echo '<th class="data">';
703
        $this->view->printHelp($this->lang['strreindex'], 'pg.index.reindex');
704
        echo '</th>';
705
        echo '</tr>';
706
707
        // Vacuum
708
        echo '<tr class="row1">' . \PHP_EOL;
709
        echo '<td style="text-align: center; vertical-align: bottom">' . \PHP_EOL;
710
        echo '<form action="' . \containerInstance()->subFolder . "/src/views/{$script}\" method=\"post\">" . \PHP_EOL;
711
712
        echo '<p><input type="hidden" name="action" value="confirm_vacuum" />' . \PHP_EOL;
713
        echo $this->view->form;
714
        echo $table_hidden_inputs;
715
        echo "<input type=\"submit\" value=\"{$this->lang['strvacuum']}\" /></p>" . \PHP_EOL;
716
        echo '</form>' . \PHP_EOL;
717
        echo '</td>' . \PHP_EOL;
718
719
        // Analyze
720
        echo '<td style="text-align: center; vertical-align: bottom">' . \PHP_EOL;
721
        echo '<form action="' . \containerInstance()->subFolder . "/src/views/{$script}\" method=\"post\">" . \PHP_EOL;
722
        echo '<p><input type="hidden" name="action" value="confirm_analyze" />' . \PHP_EOL;
723
        echo $this->view->form;
724
        echo $table_hidden_inputs;
725
        echo "<input type=\"submit\" value=\"{$this->lang['stranalyze']}\" /></p>" . \PHP_EOL;
726
        echo '</form>' . \PHP_EOL;
727
        echo '</td>' . \PHP_EOL;
728
729
        // Cluster
730
        echo $reclusterconf;
731
732
        // Reindex
733
        echo '<td style="text-align: center; vertical-align: bottom">' . \PHP_EOL;
734
        echo '<form action="' . \containerInstance()->subFolder . "/src/views/{$script}\" method=\"post\">" . \PHP_EOL;
735
        echo '<p><input type="hidden" name="action" value="confirm_reindex" />' . \PHP_EOL;
736
        echo $this->view->form;
737
        echo $table_hidden_inputs;
738
        echo "<input type=\"submit\" value=\"{$this->lang['strreindex']}\" /></p>" . \PHP_EOL;
739
        echo '</form>' . \PHP_EOL;
740
        echo '</td>' . \PHP_EOL;
741
        echo '</tr>' . \PHP_EOL;
742
        echo '</table>' . \PHP_EOL;
743
744
        // Autovacuum
745
        $this->_printAutoVacuumConf($data, $type);
746
    }
747
748
    public function adminActions($action, $type)
749
    {
750
        if ('database' === $type) {
751
            $_REQUEST['object'] = $_REQUEST['database'];
752
        } else {
753
            // $_REQUEST['table'] is no set if we are in the schema page
754
            $_REQUEST['object'] = ($_REQUEST['table'] ?? '');
755
756
            if (\is_array($_REQUEST['object'])) {
757
                return false;
758
            }
759
        }
760
761
        if (isset($_POST['cancel'])) {
762
            $action = 'admin';
763
        }
764
765
        switch ($action) {
766
            case 'admin':
767
                $this->doAdmin($type);
768
769
                break;
770
            case 'confirm_cluster':
771
                $this->confirmCluster($type);
772
773
                break;
774
            case 'confirm_reindex':
775
                $this->confirmReindex($type);
776
777
                break;
778
            case 'confirm_analyze':
779
                $this->confirmAnalyze($type);
780
781
                break;
782
            case 'confirm_vacuum':
783
                $this->confirmVacuum($type);
784
785
                break;
786
            case 'confeditautovac':
787
                $this->confirmEditAutovacuum($type);
788
789
                break;
790
            case 'confdelautovac':
791
                $this->confirmDropAutovacuum($type);
792
793
                break;
794
            case 'cluster':
795
                $this->doCluster($type);
796
797
                break;
798
            case 'reindex':
799
                $this->doReindex($type);
800
801
                break;
802
            case 'analyze':
803
                $this->doAnalyze($type);
804
805
                break;
806
            case 'vacuum':
807
                $this->doVacuum($type);
808
809
                break;
810
            case 'editautovac':
811
                $this->doEditAutovacuum($type);
812
813
                break;
814
            case 'delautovac':
815
                $this->doDropAutovacuum($type);
816
817
                break;
818
819
            default:
820
                return false;
821
        }
822
823
        return true;
824
    }
825
826
    abstract public function doDefault($msg = '');
827
828
    /**
829
     * Prints a trail.
830
     *
831
     * @param array|string $trail    The trail
832
     * @param bool         $do_print The do print
833
     *
834
     * @return string ( description_of_the_return_value )
835
     */
836
    abstract public function printTrail($trail = [], bool $do_print = true);
837
838
    abstract public function printTitle(string $title, ?string $help = null, bool $do_print = true);
839
840
    abstract public function printMsg($msg, $do_print = true);
841
842
    abstract public function printTabs(string $tabs, string $activetab, bool $do_print = true);
843
844
    abstract public function printTable(&$tabledata, &$columns, &$actions, $place, $nodata = '', $pre_fn = null);
845
846
    private function _getReclusterConf($data, $type, $table_hidden_inputs)
847
    {
848
        if (!$data->hasRecluster()) {
849
            return ['', ''];
850
        }
851
        $script = $this->script;
852
        $recluster_help = \sprintf(
853
            '<th class="data">%s</th>',
854
            $this->view->printHelp($this->lang['strclusterindex'], 'pg.index.cluster', false)
855
        );
856
857
        $disabled = '';
858
        $reclusterconf = '<td style="text-align: center; vertical-align: bottom">' . \PHP_EOL;
859
        $reclusterconf .= '<form action="' . \containerInstance()->subFolder . "/src/views/{$script}\" method=\"post\">" . \PHP_EOL;
860
        $reclusterconf .= $this->view->form;
861
        $reclusterconf .= $table_hidden_inputs;
862
863
        if ('table' === $type && !$data->alreadyClustered($_REQUEST['object'])) {
864
            $disabled = 'disabled="disabled" ';
865
            $reclusterconf .= "{$this->lang['strnoclusteravailable']}<br />";
866
        }
867
        $reclusterconf .= '<p><input type="hidden" name="action" value="confirm_cluster" />' . \PHP_EOL;
868
        $reclusterconf .= "<input type=\"submit\" value=\"{$this->lang['strclusterindex']}\" {$disabled}/></p>" . \PHP_EOL;
869
        $reclusterconf .= '</form>' . \PHP_EOL;
870
        $reclusterconf .= '</td>' . \PHP_EOL;
871
872
        return [$recluster_help, $reclusterconf];
873
    }
874
875
    private function _printAutoVacuumConf($data, $type): void
876
    {
877
        if (!$data->hasAutovacuum()) {
878
            return;
879
        }
880
        $script = $this->script;
881
        // get defaults values for autovacuum
882
        $defaults = $data->getAutovacuum();
883
        // Fetch the autovacuum properties from the database or table if != ''
884
        if ('table' === $type) {
885
            $autovac = $data->getTableAutovacuum($_REQUEST['table']);
886
        } else {
887
            $autovac = $data->getTableAutovacuum();
888
        }
889
890
        echo "<br /><br /><h2>{$this->lang['strvacuumpertable']}</h2>";
891
        echo '<p>' . (('on' === $defaults['autovacuum']) ? $this->lang['strturnedon'] : $this->lang['strturnedoff']) . '</p>';
892
        echo "<p class=\"message\">{$this->lang['strnotdefaultinred']}</p>";
893
894
        $enlight = static function ($f, $p) {
895
            if (isset($f[$p[0]]) && ($f[$p[0]] !== $p[1])) {
896
                return '<span style="color:#F33;font-weight:bold">' . \htmlspecialchars($f[$p[0]]) . '</span>';
897
            }
898
899
            return \htmlspecialchars($p[1]);
900
        };
901
902
        $columns = [
903
            'namespace' => [
904
                'title' => $this->lang['strschema'],
905
                'field' => Decorator::field('nspname'),
906
                'url' => \containerInstance()->subFolder . "/redirect/schema?{$this->misc->href}&amp;",
907
                'vars' => ['schema' => 'nspname'],
908
            ],
909
            'relname' => [
910
                'title' => $this->lang['strtable'],
911
                'field' => Decorator::field('relname'),
912
                'url' => \containerInstance()->subFolder . "/redirect/table?{$this->misc->href}&amp;",
913
                'vars' => ['table' => 'relname', 'schema' => 'nspname'],
914
            ],
915
            'autovacuum_enabled' => [
916
                'title' => $this->lang['strenabled'],
917
                'field' => Decorator::callback($enlight, ['autovacuum_enabled',
918
                    $defaults['autovacuum'], ]),
919
                'type' => 'verbatim',
920
            ],
921
            'autovacuum_vacuum_threshold' => [
922
                'title' => $this->lang['strvacuumbasethreshold'],
923
                'field' => Decorator::callback($enlight, ['autovacuum_vacuum_threshold',
924
                    $defaults['autovacuum_vacuum_threshold'], ]),
925
                'type' => 'verbatim',
926
            ],
927
            'autovacuum_vacuum_scale_factor' => [
928
                'title' => $this->lang['strvacuumscalefactor'],
929
                'field' => Decorator::callback($enlight, ['autovacuum_vacuum_scale_factor',
930
                    $defaults['autovacuum_vacuum_scale_factor'], ]),
931
                'type' => 'verbatim',
932
            ],
933
            'autovacuum_analyze_threshold' => [
934
                'title' => $this->lang['stranalybasethreshold'],
935
                'field' => Decorator::callback($enlight, ['autovacuum_analyze_threshold',
936
                    $defaults['autovacuum_analyze_threshold'], ]),
937
                'type' => 'verbatim',
938
            ],
939
            'autovacuum_analyze_scale_factor' => [
940
                'title' => $this->lang['stranalyzescalefactor'],
941
                'field' => Decorator::callback($enlight, ['autovacuum_analyze_scale_factor',
942
                    $defaults['autovacuum_analyze_scale_factor'], ]),
943
                'type' => 'verbatim',
944
            ],
945
            'autovacuum_vacuum_cost_delay' => [
946
                'title' => $this->lang['strvacuumcostdelay'],
947
                'field' => Decorator::concat(Decorator::callback($enlight, ['autovacuum_vacuum_cost_delay',
948
                    $defaults['autovacuum_vacuum_cost_delay'], ]), 'ms'),
949
                'type' => 'verbatim',
950
            ],
951
            'autovacuum_vacuum_cost_limit' => [
952
                'title' => $this->lang['strvacuumcostlimit'],
953
                'field' => Decorator::callback($enlight, ['autovacuum_vacuum_cost_limit',
954
                    $defaults['autovacuum_vacuum_cost_limit'], ]),
955
                'type' => 'verbatim',
956
            ],
957
        ];
958
959
        // Maybe we need to check permissions here?
960
        $columns['actions'] = ['title' => $this->lang['stractions']];
961
962
        $actions = [
963
            'edit' => [
964
                'content' => $this->lang['stredit'],
965
                'attr' => [
966
                    'href' => [
967
                        'url' => $script,
968
                        'urlvars' => [
969
                            'subject' => $type,
970
                            'action' => 'confeditautovac',
971
                            'schema' => Decorator::field('nspname'),
972
                            'table' => Decorator::field('relname'),
973
                        ],
974
                    ],
975
                ],
976
            ],
977
            'delete' => [
978
                'content' => $this->lang['strdelete'],
979
                'attr' => [
980
                    'href' => [
981
                        'url' => $script,
982
                        'urlvars' => [
983
                            'subject' => $type,
984
                            'action' => 'confdelautovac',
985
                            'schema' => Decorator::field('nspname'),
986
                            'table' => Decorator::field('relname'),
987
                        ],
988
                    ],
989
                ],
990
            ],
991
        ];
992
993
        if ('table' === $type) {
994
            unset(
995
                $actions['edit']['vars']['schema'],
996
                $actions['delete']['vars']['schema'],
997
                $columns['namespace'],
998
                $columns['relname']
999
            );
1000
        }
1001
1002
        echo $this->printTable($autovac, $columns, $actions, 'admin-admin', $this->lang['strnovacuumconf']);
1003
1004
        if (('table' === $type) && (0 === $autovac->recordCount())) {
1005
            echo '<br />';
1006
1007
            echo '<a href="' . \containerInstance()->subFolder . "/src/views/tables?action=confeditautovac&amp;{$this->misc->href}&amp;table=";
1008
            echo \htmlspecialchars($_REQUEST['table']);
1009
            echo "\">{$this->lang['straddvacuumtable']}</a>";
1010
        }
1011
    }
1012
}
1013