Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/HuasoFoundries/phpPgAdmin6.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/Traits/AdminTrait.php')
-rw-r--r--src/Traits/AdminTrait.php1076
1 files changed, 1076 insertions, 0 deletions
diff --git a/src/Traits/AdminTrait.php b/src/Traits/AdminTrait.php
new file mode 100644
index 00000000..2eb43182
--- /dev/null
+++ b/src/Traits/AdminTrait.php
@@ -0,0 +1,1076 @@
+<?php
+
+/**
+ * PHPPgAdmin6
+ */
+
+namespace PHPPgAdmin\Traits;
+
+use IteratorAggregate;
+use PHPPgAdmin\Decorators\Decorator;
+
+/**
+ * Common trait for admin features.
+ */
+trait AdminTrait
+{
+ /**
+ * Show confirmation of cluster.
+ *
+ * @param mixed $type
+ */
+ public function confirmCluster($type): void
+ {
+ $this->script = ('database' === $type) ? 'database' : 'tables';
+
+ $script = $this->script;
+
+ if (('table' === $type) && empty($_REQUEST['table']) && empty($_REQUEST['ma'])) {
+ $this->doDefault($this->lang['strspecifytabletocluster']);
+
+ return;
+ }
+
+ if (isset($_REQUEST['ma'])) {
+ $this->printTrail('schema');
+ $this->printTitle($this->lang['strclusterindex'], 'pg.index.cluster');
+
+ echo '<form action="' . \containerInstance()->subFolder . "/src/views/{$script}\" method=\"post\">" . \PHP_EOL;
+
+ foreach ($_REQUEST['ma'] as $v) {
+ $a = \unserialize(\htmlspecialchars_decode($v, \ENT_QUOTES));
+ echo '<p>', \sprintf(
+ $this->lang['strconfclustertable'],
+ $this->misc->printVal($a['table'])
+ ), '</p>' . \PHP_EOL;
+ echo '<input type="hidden" name="table[]" value="', \htmlspecialchars($a['table']), '" />' . \PHP_EOL;
+ } // END if multi cluster
+ } else {
+ $this->printTrail($type);
+ $this->printTitle($this->lang['strclusterindex'], 'pg.index.cluster');
+
+ echo '<form action="' . \containerInstance()->subFolder . "/src/views/{$script}\" method=\"post\">" . \PHP_EOL;
+
+ if ('table' === $type) {
+ echo '<p>', \sprintf(
+ $this->lang['strconfclustertable'],
+ $this->misc->printVal($_REQUEST['object'])
+ ), '</p>' . \PHP_EOL;
+ echo '<input type="hidden" name="table" value="', \htmlspecialchars($_REQUEST['object']), '" />' . \PHP_EOL;
+ } else {
+ echo '<p>', \sprintf(
+ $this->lang['strconfclusterdatabase'],
+ $this->misc->printVal($_REQUEST['object'])
+ ), '</p>' . \PHP_EOL;
+ echo '<input type="hidden" name="table" value="" />' . \PHP_EOL;
+ }
+ }
+ echo '<input type="hidden" name="action" value="cluster" />' . \PHP_EOL;
+
+ echo $this->view->form;
+
+ echo "<input type=\"submit\" name=\"cluster\" value=\"{$this->lang['strcluster']}\" />\n"; //TODO
+ echo "<input type=\"submit\" name=\"cancel\" value=\"{$this->lang['strcancel']}\" />" . \PHP_EOL;
+ echo "</form>\n"; // END single cluster
+ }
+
+ /**
+ * Show confirmation of reindex.
+ *
+ * @param mixed $type
+ */
+ public function confirmReindex($type): void
+ {
+ $this->script = ('database' === $type) ? 'database' : 'tables';
+ $script = $this->script;
+ $this->misc = $this->misc;
+ $data = $this->misc->getDatabaseAccessor();
+
+ if (('table' === $type) && empty($_REQUEST['table']) && empty($_REQUEST['ma'])) {
+ $this->doDefault($this->lang['strspecifytabletoreindex']);
+
+ return;
+ }
+
+ if (isset($_REQUEST['ma'])) {
+ $this->printTrail('schema');
+ $this->printTitle($this->lang['strreindex'], 'pg.reindex');
+
+ echo '<form action="' . \containerInstance()->subFolder . "/src/views/{$script}\" method=\"post\">" . \PHP_EOL;
+
+ foreach ($_REQUEST['ma'] as $v) {
+ $a = \unserialize(\htmlspecialchars_decode($v, \ENT_QUOTES));
+ echo '<p>', \sprintf(
+ $this->lang['strconfreindextable'],
+ $this->misc->printVal($a['table'])
+ ), '</p>' . \PHP_EOL;
+ echo '<input type="hidden" name="table[]" value="', \htmlspecialchars($a['table']), '" />' . \PHP_EOL;
+ } // END if multi reindex
+ } else {
+ $this->printTrail($type);
+ $this->printTitle($this->lang['strreindex'], 'pg.reindex');
+
+ echo '<form action="' . \containerInstance()->subFolder . "/src/views/{$script}\" method=\"post\">" . \PHP_EOL;
+
+ if ('table' === $type) {
+ echo '<p>', \sprintf(
+ $this->lang['strconfreindextable'],
+ $this->misc->printVal($_REQUEST['object'])
+ ), '</p>' . \PHP_EOL;
+ echo '<input type="hidden" name="table" value="', \htmlspecialchars($_REQUEST['object']), '" />' . \PHP_EOL;
+ } else {
+ echo '<p>', \sprintf(
+ $this->lang['strconfreindexdatabase'],
+ $this->misc->printVal($_REQUEST['object'])
+ ), '</p>' . \PHP_EOL;
+ echo '<input type="hidden" name="table" value="" />' . \PHP_EOL;
+ }
+ }
+ echo '<input type="hidden" name="action" value="reindex" />' . \PHP_EOL;
+
+ if ($data->hasForceReindex()) {
+ echo "<p><input type=\"checkbox\" id=\"reindex_force\" name=\"reindex_force\" /><label for=\"reindex_force\">{$this->lang['strforce']}</label></p>" . \PHP_EOL;
+ }
+
+ echo $this->view->form;
+
+ echo "<input type=\"submit\" name=\"reindex\" value=\"{$this->lang['strreindex']}\" />\n"; //TODO
+ echo "<input type=\"submit\" name=\"cancel\" value=\"{$this->lang['strcancel']}\" />" . \PHP_EOL;
+ echo "</form>\n"; // END single reindex
+ }
+
+ /**
+ * Show confirmation of analyze.
+ *
+ * @param mixed $type
+ */
+ public function confirmAnalyze($type): void
+ {
+ $this->script = ('database' === $type) ? 'database' : 'tables';
+
+ $script = $this->script;
+
+ if (('table' === $type) && empty($_REQUEST['table']) && empty($_REQUEST['ma'])) {
+ $this->doDefault($this->lang['strspecifytabletoanalyze']);
+
+ return;
+ }
+
+ if (isset($_REQUEST['ma'])) {
+ $this->printTrail('schema');
+ $this->printTitle($this->lang['stranalyze'], 'pg.analyze');
+
+ echo '<form action="' . \containerInstance()->subFolder . "/src/views/{$script}\" method=\"post\">" . \PHP_EOL;
+
+ foreach ($_REQUEST['ma'] as $v) {
+ $a = \unserialize(\htmlspecialchars_decode($v, \ENT_QUOTES));
+ echo '<p>', \sprintf(
+ $this->lang['strconfanalyzetable'],
+ $this->misc->printVal($a['table'])
+ ), '</p>' . \PHP_EOL;
+ echo '<input type="hidden" name="table[]" value="', \htmlspecialchars($a['table']), '" />' . \PHP_EOL;
+ } // END if multi analyze
+ } else {
+ $this->printTrail($type);
+ $this->printTitle($this->lang['stranalyze'], 'pg.analyze');
+
+ echo '<form action="' . \containerInstance()->subFolder . "/src/views/{$script}\" method=\"post\">" . \PHP_EOL;
+
+ if ('table' === $type) {
+ echo '<p>', \sprintf(
+ $this->lang['strconfanalyzetable'],
+ $this->misc->printVal($_REQUEST['object'])
+ ), '</p>' . \PHP_EOL;
+ echo '<input type="hidden" name="table" value="', \htmlspecialchars($_REQUEST['object']), '" />' . \PHP_EOL;
+ } else {
+ echo '<p>', \sprintf(
+ $this->lang['strconfanalyzedatabase'],
+ $this->misc->printVal($_REQUEST['object'])
+ ), '</p>' . \PHP_EOL;
+ echo '<input type="hidden" name="table" value="" />' . \PHP_EOL;
+ }
+ }
+ echo '<input type="hidden" name="action" value="analyze" />' . \PHP_EOL;
+ echo $this->view->form;
+
+ echo "<input type=\"submit\" name=\"analyze\" value=\"{$this->lang['stranalyze']}\" />\n"; //TODO
+ echo "<input type=\"submit\" name=\"cancel\" value=\"{$this->lang['strcancel']}\" />" . \PHP_EOL;
+ echo "</form>\n"; // END single analyze
+ }
+
+ /**
+ * Show confirmation of vacuum.
+ *
+ * @param mixed $type
+ */
+ public function confirmVacuum($type): void
+ {
+ $script = ('database' === $type) ? 'database' : 'tables';
+
+ if (('table' === $type) && empty($_REQUEST['table']) && empty($_REQUEST['ma'])) {
+ $this->doDefault($this->lang['strspecifytabletovacuum']);
+
+ return;
+ }
+
+ if (isset($_REQUEST['ma'])) {
+ $this->printTrail('schema');
+ $this->printTitle($this->lang['strvacuum'], 'pg.vacuum');
+
+ echo '<form action="' . \containerInstance()->subFolder . "/src/views/{$script}\" method=\"post\">" . \PHP_EOL;
+
+ foreach ($_REQUEST['ma'] as $v) {
+ $a = \unserialize(\htmlspecialchars_decode($v, \ENT_QUOTES));
+ echo '<p>', \sprintf(
+ $this->lang['strconfvacuumtable'],
+ $this->misc->printVal($a['table'])
+ ), '</p>' . \PHP_EOL;
+ echo '<input type="hidden" name="table[]" value="', \htmlspecialchars($a['table']), '" />' . \PHP_EOL;
+ }
+ } else {
+ // END if multi vacuum
+ $this->printTrail($type);
+ $this->printTitle($this->lang['strvacuum'], 'pg.vacuum');
+
+ echo '<form action="' . \containerInstance()->subFolder . "/src/views/{$script}\" method=\"post\">" . \PHP_EOL;
+
+ if ('table' === $type) {
+ echo '<p>', \sprintf(
+ $this->lang['strconfvacuumtable'],
+ $this->misc->printVal($_REQUEST['object'])
+ ), '</p>' . \PHP_EOL;
+ echo '<input type="hidden" name="table" value="', \htmlspecialchars($_REQUEST['object']), '" />' . \PHP_EOL;
+ } else {
+ echo '<p>', \sprintf(
+ $this->lang['strconfvacuumdatabase'],
+ $this->misc->printVal($_REQUEST['object'])
+ ), '</p>' . \PHP_EOL;
+ echo '<input type="hidden" name="table" value="" />' . \PHP_EOL;
+ }
+ }
+ echo '<input type="hidden" name="action" value="vacuum" />' . \PHP_EOL;
+ echo $this->view->form;
+ echo "<p><input type=\"checkbox\" id=\"vacuum_full\" name=\"vacuum_full\" /> <label for=\"vacuum_full\">{$this->lang['strfull']}</label></p>" . \PHP_EOL;
+ echo "<p><input type=\"checkbox\" id=\"vacuum_analyze\" name=\"vacuum_analyze\" /> <label for=\"vacuum_analyze\">{$this->lang['stranalyze']}</label></p>" . \PHP_EOL;
+ echo "<p><input type=\"checkbox\" id=\"vacuum_freeze\" name=\"vacuum_freeze\" /> <label for=\"vacuum_freeze\">{$this->lang['strfreeze']}</label></p>" . \PHP_EOL;
+ echo "<input type=\"submit\" name=\"vacuum\" value=\"{$this->lang['strvacuum']}\" />" . \PHP_EOL;
+ echo "<input type=\"submit\" name=\"cancel\" value=\"{$this->lang['strcancel']}\" />" . \PHP_EOL;
+ echo "</form>\n"; // END single vacuum
+ }
+
+ /**
+ * Add or Edit autovacuum params.
+ *
+ * @param mixed $type
+ * @param mixed $msg
+ */
+ public function confirmEditAutovacuum($type, $msg = ''): void
+ {
+ $data = $this->misc->getDatabaseAccessor();
+
+ if (empty($_REQUEST['table'])) {
+ $this->doAdmin($type, $this->lang['strspecifyeditvacuumtable']);
+
+ return;
+ }
+
+ $script = ('database' === $type) ? 'database' : 'tables';
+
+ $this->printTrail($type);
+ $this->printTitle(\sprintf($this->lang['streditvacuumtable'], $this->misc->printVal($_REQUEST['table'])));
+ $this->printMsg(\sprintf($msg, $this->misc->printVal($_REQUEST['table'])));
+
+ if (empty($_REQUEST['table'])) {
+ $this->doAdmin($type, $this->lang['strspecifyeditvacuumtable']);
+
+ return;
+ }
+
+ $old_val = $data->getTableAutovacuum($_REQUEST['table']);
+ $defaults = $data->getAutovacuum();
+ $old_val = $old_val->fields;
+
+ if (isset($old_val['autovacuum_enabled']) && ('off' === $old_val['autovacuum_enabled'])) {
+ $enabled = '';
+ $disabled = 'checked="checked"';
+ } else {
+ $enabled = 'checked="checked"';
+ $disabled = '';
+ }
+
+ if (!isset($old_val['autovacuum_vacuum_threshold'])) {
+ $old_val['autovacuum_vacuum_threshold'] = '';
+ }
+
+ if (!isset($old_val['autovacuum_vacuum_scale_factor'])) {
+ $old_val['autovacuum_vacuum_scale_factor'] = '';
+ }
+
+ if (!isset($old_val['autovacuum_analyze_threshold'])) {
+ $old_val['autovacuum_analyze_threshold'] = '';
+ }
+
+ if (!isset($old_val['autovacuum_analyze_scale_factor'])) {
+ $old_val['autovacuum_analyze_scale_factor'] = '';
+ }
+
+ if (!isset($old_val['autovacuum_vacuum_cost_delay'])) {
+ $old_val['autovacuum_vacuum_cost_delay'] = '';
+ }
+
+ if (!isset($old_val['autovacuum_vacuum_cost_limit'])) {
+ $old_val['autovacuum_vacuum_cost_limit'] = '';
+ }
+
+ echo '<form action="' . \containerInstance()->subFolder . "/src/views/{$script}\" method=\"post\">" . \PHP_EOL;
+ echo $this->view->form;
+ echo '<input type="hidden" name="action" value="editautovac" />' . \PHP_EOL;
+ echo \sprintf('<input type="hidden" name="table" value="%s" />%s', \htmlspecialchars($_REQUEST['table']), \PHP_EOL);
+
+ echo "<br />\n<br />\n<table>" . \PHP_EOL;
+ echo "\t<tr><td>&nbsp;</td>" . \PHP_EOL;
+ echo "<th class=\"data\">{$this->lang['strnewvalues']}</th><th class=\"data\">{$this->lang['strdefaultvalues']}</th></tr>" . \PHP_EOL;
+ echo "\t<tr><th class=\"data left\">{$this->lang['strenable']}</th>" . \PHP_EOL;
+ echo '<td class="data1">' . \PHP_EOL;
+ echo "<label for=\"on\">on</label><input type=\"radio\" name=\"autovacuum_enabled\" id=\"on\" value=\"on\" {$enabled} />" . \PHP_EOL;
+ echo "<label for=\"off\">off</label><input type=\"radio\" name=\"autovacuum_enabled\" id=\"off\" value=\"off\" {$disabled} /></td>" . \PHP_EOL;
+ echo "<th class=\"data left\">{$defaults['autovacuum']}</th></tr>" . \PHP_EOL;
+ echo "\t<tr><th class=\"data left\">{$this->lang['strvacuumbasethreshold']}</th>" . \PHP_EOL;
+ echo "<td class=\"data1\"><input type=\"text\" name=\"autovacuum_vacuum_threshold\" value=\"{$old_val['autovacuum_vacuum_threshold']}\" /></td>" . \PHP_EOL;
+ echo "<th class=\"data left\">{$defaults['autovacuum_vacuum_threshold']}</th></tr>" . \PHP_EOL;
+ echo "\t<tr><th class=\"data left\">{$this->lang['strvacuumscalefactor']}</th>" . \PHP_EOL;
+ echo "<td class=\"data1\"><input type=\"text\" name=\"autovacuum_vacuum_scale_factor\" value=\"{$old_val['autovacuum_vacuum_scale_factor']}\" /></td>" . \PHP_EOL;
+ echo "<th class=\"data left\">{$defaults['autovacuum_vacuum_scale_factor']}</th></tr>" . \PHP_EOL;
+ echo "\t<tr><th class=\"data left\">{$this->lang['stranalybasethreshold']}</th>" . \PHP_EOL;
+ echo "<td class=\"data1\"><input type=\"text\" name=\"autovacuum_analyze_threshold\" value=\"{$old_val['autovacuum_analyze_threshold']}\" /></td>" . \PHP_EOL;
+ echo "<th class=\"data left\">{$defaults['autovacuum_analyze_threshold']}</th></tr>" . \PHP_EOL;
+ echo "\t<tr><th class=\"data left\">{$this->lang['stranalyzescalefactor']}</th>" . \PHP_EOL;
+ echo "<td class=\"data1\"><input type=\"text\" name=\"autovacuum_analyze_scale_factor\" value=\"{$old_val['autovacuum_analyze_scale_factor']}\" /></td>" . \PHP_EOL;
+ echo "<th class=\"data left\">{$defaults['autovacuum_analyze_scale_factor']}</th></tr>" . \PHP_EOL;
+ echo "\t<tr><th class=\"data left\">{$this->lang['strvacuumcostdelay']}</th>" . \PHP_EOL;
+ echo "<td class=\"data1\"><input type=\"text\" name=\"autovacuum_vacuum_cost_delay\" value=\"{$old_val['autovacuum_vacuum_cost_delay']}\" /></td>" . \PHP_EOL;
+ echo "<th class=\"data left\">{$defaults['autovacuum_vacuum_cost_delay']}</th></tr>" . \PHP_EOL;
+ echo "\t<tr><th class=\"data left\">{$this->lang['strvacuumcostlimit']}</th>" . \PHP_EOL;
+ echo "<td class=\"datat1\"><input type=\"text\" name=\"autovacuum_vacuum_cost_limit\" value=\"{$old_val['autovacuum_vacuum_cost_limit']}\" /></td>" . \PHP_EOL;
+ echo "<th class=\"data left\">{$defaults['autovacuum_vacuum_cost_limit']}</th></tr>" . \PHP_EOL;
+ echo '</table>' . \PHP_EOL;
+ echo '<br />';
+ echo '<br />';
+ echo "<input type=\"submit\" name=\"save\" value=\"{$this->lang['strsave']}\" />" . \PHP_EOL;
+ echo \sprintf('<input type="submit" name="cancel" value="%s" /></p>%s', $this->lang['strcancel'], \PHP_EOL);
+
+ echo '</form>' . \PHP_EOL;
+ }
+
+ /**
+ * Confirm drop autovacuum params for a table.
+ *
+ * @param mixed $type
+ */
+ public function confirmDropAutovacuum($type): void
+ {
+ $script = ('database' === $type) ? 'database' : 'tables';
+
+ if (empty($_REQUEST['table'])) {
+ $this->doAdmin($type, $this->lang['strspecifydelvacuumtable']);
+
+ return;
+ }
+
+ $this->printTrail($type);
+ $this->printTabs($type, 'admin');
+
+ \printf(
+ "<p>{$this->lang['strdelvacuumtable']}</p>\n",
+ $this->misc->printVal("\"{$_GET['schema']}\".\"{$_GET['table']}\"")
+ );
+
+ echo "<form style=\"float: left\" action=\"{$script}\" method=\"post\">" . \PHP_EOL;
+ echo '<input type="hidden" name="action" value="delautovac" />' . \PHP_EOL;
+ echo $this->view->form;
+ echo \sprintf('<input type="hidden" name="table" value="%s" />%s', \htmlspecialchars($_REQUEST['table']), \PHP_EOL);
+ echo '<input type="hidden" name="rel" value="', \htmlspecialchars(\serialize([$_REQUEST['schema'], $_REQUEST['table']])), '" />' . \PHP_EOL;
+ echo "<input type=\"submit\" name=\"yes\" value=\"{$this->lang['stryes']}\" />" . \PHP_EOL;
+ echo "<input type=\"submit\" name=\"cancel\" value=\"{$this->lang['strcancel']}\" />" . \PHP_EOL;
+ echo '</form>' . \PHP_EOL;
+ }
+
+ /**
+ * perform cluster.
+ *
+ * @param mixed $type
+ */
+ public function doCluster($type): void
+ {
+ $data = $this->misc->getDatabaseAccessor();
+
+ if (('table' === $type) && empty($_REQUEST['table']) && empty($_REQUEST['ma'])) {
+ $this->doDefault($this->lang['strspecifytabletocluster']);
+
+ return;
+ }
+
+ $msg = '';
+ //If multi table cluster
+ if ('table' === $type) {
+ // cluster one or more table
+ if (\is_array($_REQUEST['table'])) {
+ foreach ($_REQUEST['table'] as $o) {
+ [$status, $sql] = $data->clusterIndex($o);
+ $msg .= \sprintf('%s<br />', $sql);
+
+ if (0 === $status) {
+ $msg .= \sprintf(
+ '%s: %s<br />',
+ \htmlentities($o, \ENT_QUOTES, 'UTF-8'),
+ $this->lang['strclusteredgood']
+ );
+ } else {
+ $this->doDefault(\sprintf(
+ '%s %s%s: %s<br />',
+ $type,
+ $msg,
+ \htmlentities($o, \ENT_QUOTES, 'UTF-8'),
+ $this->lang['strclusteredbad']
+ ));
+
+ return;
+ }
+ }
+ // Everything went fine, back to the Default page....
+ $this->doDefault($msg);
+ } else {
+ [$status, $sql] = $data->clusterIndex($_REQUEST['object']);
+ $msg .= \sprintf('%s<br />', $sql);
+
+ if (0 === $status) {
+ $this->doAdmin($type, $msg . $this->lang['strclusteredgood']);
+ } else {
+ $this->doAdmin($type, $msg . $this->lang['strclusteredbad']);
+ }
+ }
+ } else {
+ // Cluster all tables in database
+ [$status, $sql] = $data->clusterIndex();
+ $msg .= \sprintf('%s<br />', $sql);
+
+ if (0 === $status) {
+ $this->doAdmin($type, $msg . $this->lang['strclusteredgood']);
+ } else {
+ $this->doAdmin($type, $msg . $this->lang['strclusteredbad']);
+ }
+ }
+ }
+
+ /**
+ * perform reindex.
+ *
+ * @param mixed $type
+ */
+ public function doReindex($type): void
+ {
+ $this->misc = $this->misc;
+ $data = $this->misc->getDatabaseAccessor();
+
+ if (('table' === $type) && empty($_REQUEST['table']) && empty($_REQUEST['ma'])) {
+ $this->doDefault($this->lang['strspecifytabletoreindex']);
+
+ return;
+ }
+
+ //If multi table reindex
+ if (('table' === $type) && \is_array($_REQUEST['table'])) {
+ $msg = '';
+
+ foreach ($_REQUEST['table'] as $o) {
+ $status = $data->reindex(\mb_strtoupper($type), $o, isset($_REQUEST['reindex_force']));
+
+ if (0 === $status) {
+ $msg .= \sprintf(
+ '%s: %s<br />',
+ \htmlentities($o, \ENT_QUOTES, 'UTF-8'),
+ $this->lang['strreindexgood']
+ );
+ } else {
+ $this->doDefault(\sprintf(
+ '%s %s%s: %s<br />',
+ $type,
+ $msg,
+ \htmlentities($o, \ENT_QUOTES, 'UTF-8'),
+ $this->lang['strreindexbad']
+ ));
+
+ return;
+ }
+ }
+ // Everything went fine, back to the Default page....
+ $this->view->setReloadBrowser(true);
+ $this->doDefault($msg);
+ } else {
+ $status = $data->reindex(\mb_strtoupper($type), $_REQUEST['object'], isset($_REQUEST['reindex_force']));
+
+ if (0 === $status) {
+ $this->view->setReloadBrowser(true);
+ $this->doAdmin($type, $this->lang['strreindexgood']);
+ } else {
+ $this->doAdmin($type, $this->lang['strreindexbad']);
+ }
+ }
+ }
+
+ /**
+ * perform analyze.
+ *
+ * @param mixed $type
+ */
+ public function doAnalyze($type): void
+ {
+ $data = $this->misc->getDatabaseAccessor();
+
+ if (('table' === $type) && empty($_REQUEST['table']) && empty($_REQUEST['ma'])) {
+ $this->doDefault($this->lang['strspecifytabletoanalyze']);
+
+ return;
+ }
+
+ //If multi table analyze
+ if (('table' === $type) && \is_array($_REQUEST['table'])) {
+ $msg = '';
+
+ foreach ($_REQUEST['table'] as $o) {
+ $status = $data->analyzeDB($o);
+
+ if (0 === $status) {
+ $msg .= \sprintf(
+ '%s: %s<br />',
+ \htmlentities($o, \ENT_QUOTES, 'UTF-8'),
+ $this->lang['stranalyzegood']
+ );
+ } else {
+ $this->doDefault(\sprintf(
+ '%s %s%s: %s<br />',
+ $type,
+ $msg,
+ \htmlentities($o, \ENT_QUOTES, 'UTF-8'),
+ $this->lang['stranalyzebad']
+ ));
+
+ return;
+ }
+ }
+ // Everything went fine, back to the Default page....
+ $this->view->setReloadBrowser(true);
+ $this->doDefault($msg);
+ } else {
+ //we must pass table here. When empty, analyze the whole db
+ $status = $data->analyzeDB($_REQUEST['table']);
+
+ if (0 === $status) {
+ $this->view->setReloadBrowser(true);
+ $this->doAdmin($type, $this->lang['stranalyzegood']);
+ } else {
+ $this->doAdmin($type, $this->lang['stranalyzebad']);
+ }
+ }
+ }
+
+ /**
+ * perform actual vacuum.
+ *
+ * @param mixed $type
+ *
+ * @return null|string
+ */
+ public function doVacuum($type)
+ {
+ $data = $this->misc->getDatabaseAccessor();
+
+ if (('table' === $type) && empty($_REQUEST['table']) && empty($_REQUEST['ma'])) {
+ $this->doDefault($this->lang['strspecifytabletovacuum']);
+
+ return;
+ }
+
+ //If multi drop
+ if (\is_array($_REQUEST['table'])) {
+ $msg = '';
+
+ foreach ($_REQUEST['table'] as $t) {
+ [$status, $sql] = $data->vacuumDB($t, isset($_REQUEST['vacuum_analyze']), isset($_REQUEST['vacuum_full']), isset($_REQUEST['vacuum_freeze']));
+
+ if (0 !== $status) {
+ return $this->doDefault(\sprintf(
+ '%s %s%s: %s<br />',
+ $type,
+ $msg,
+ \htmlentities($t, \ENT_QUOTES, 'UTF-8'),
+ $this->lang['strvacuumbad']
+ ));
+ }
+ $msg .= \sprintf(
+ '%s%s %s: %s<br />',
+ $sql,
+ \PHP_EOL,
+ \htmlentities($t, \ENT_QUOTES, 'UTF-8'),
+ $this->lang['strvacuumgood']
+ );
+ }
+ // Everything went fine, back to the Default page....
+ $this->view->setReloadBrowser(true);
+
+ return $this->doDefault($msg);
+ }
+ //we must pass table here. When empty, vacuum the whole db
+ [$status, $sql] = $data->vacuumDB($_REQUEST['table'], isset($_REQUEST['vacuum_analyze']), isset($_REQUEST['vacuum_full']), isset($_REQUEST['vacuum_freeze']));
+
+ if (0 === $status) {
+ $this->view->setReloadBrowser(true);
+
+ return $this->doAdmin($type, \sprintf('%s%s%s', $sql, \PHP_EOL, $this->lang['strvacuumgood']));
+ }
+
+ return $this->doAdmin($type, $this->lang['strvacuumbad']);
+ }
+
+ /**
+ * persist changes in autovacuum settings.
+ *
+ * @param mixed $type
+ */
+ public function doEditAutovacuum($type): void
+ {
+ $data = $this->misc->getDatabaseAccessor();
+
+ if (empty($_REQUEST['table'])) {
+ $this->doAdmin($type, $this->lang['strspecifyeditvacuumtable']);
+
+ return;
+ }
+
+ $status = $data->saveAutovacuum(
+ $_REQUEST['table'],
+ $_POST['autovacuum_enabled'],
+ $_POST['autovacuum_vacuum_threshold'],
+ $_POST['autovacuum_vacuum_scale_factor'],
+ $_POST['autovacuum_analyze_threshold'],
+ $_POST['autovacuum_analyze_scale_factor'],
+ $_POST['autovacuum_vacuum_cost_delay'],
+ $_POST['autovacuum_vacuum_cost_limit']
+ );
+
+ if (0 === $status) {
+ $this->doAdmin($type, \sprintf(
+ $this->lang['strsetvacuumtablesaved'],
+ $_REQUEST['table']
+ ));
+ } else {
+ $this->confirmEditAutovacuum($type, $this->lang['strsetvacuumtablefail']);
+ }
+ }
+
+ /**
+ * drop autovacuum settings.
+ *
+ * @param mixed $type
+ */
+ public function doDropAutovacuum($type): void
+ {
+ $data = $this->misc->getDatabaseAccessor();
+
+ if (empty($_REQUEST['table'])) {
+ $this->doAdmin($type, $this->lang['strspecifydelvacuumtable']);
+
+ return;
+ }
+
+ $status = $data->dropAutovacuum($_POST['table']);
+
+ if (0 === $status) {
+ $this->doAdmin($type, \sprintf(
+ $this->lang['strvacuumtablereset'],
+ $this->misc->printVal($_POST['table'])
+ ));
+ } else {
+ $this->doAdmin($type, \sprintf(
+ $this->lang['strdelvacuumtablefail'],
+ $this->misc->printVal($_POST['table'])
+ ));
+ }
+ }
+
+ /**
+ * Database/table administration and tuning tasks.
+ *
+ * Release: admin
+ *
+ * @param mixed $type
+ * @param mixed $msg
+ */
+ public function doAdmin($type, $msg = ''): void
+ {
+ $this->script = ('database' === $type) ? 'database' : 'tables';
+
+ $script = $this->script;
+
+ $data = $this->misc->getDatabaseAccessor();
+
+ $this->printTrail($type);
+ $this->printTabs($type, 'admin');
+ $this->printMsg($msg);
+
+ if ('database' === $type) {
+ \printf("<p>{$this->lang['stradminondatabase']}</p>\n", $this->misc->printVal($_REQUEST['object']));
+ } else {
+ \printf("<p>{$this->lang['stradminontable']}</p>\n", $this->misc->printVal($_REQUEST['object']));
+ }
+
+ echo '<table style="width: 50%">' . \PHP_EOL;
+ echo '<tr>' . \PHP_EOL;
+ echo '<th class="data">';
+ $this->view->printHelp($this->lang['strvacuum'], 'pg.admin.vacuum') . '</th>' . \PHP_EOL;
+ echo '</th>';
+ echo '<th class="data">';
+ $this->view->printHelp($this->lang['stranalyze'], 'pg.admin.analyze');
+ echo '</th>';
+
+ $table_hidden_inputs = ('table' === $type) ?
+ \sprintf(
+ '<input type="hidden" name="table" value="%s" />%s<input type="hidden" name="subject" value="table" />%s',
+ \htmlspecialchars($_REQUEST['object']),
+ \PHP_EOL,
+ \PHP_EOL
+ ) : '';
+
+ [$recluster_help, $reclusterconf] = $this->_getReclusterConf($data, $type, $table_hidden_inputs);
+
+ echo $recluster_help;
+
+ echo '<th class="data">';
+ $this->view->printHelp($this->lang['strreindex'], 'pg.index.reindex');
+ echo '</th>';
+ echo '</tr>';
+
+ // Vacuum
+ echo '<tr class="row1">' . \PHP_EOL;
+ echo '<td style="text-align: center; vertical-align: bottom">' . \PHP_EOL;
+ echo '<form action="' . \containerInstance()->subFolder . "/src/views/{$script}\" method=\"post\">" . \PHP_EOL;
+
+ echo '<p><input type="hidden" name="action" value="confirm_vacuum" />' . \PHP_EOL;
+ echo $this->view->form;
+ echo $table_hidden_inputs;
+ echo "<input type=\"submit\" value=\"{$this->lang['strvacuum']}\" /></p>" . \PHP_EOL;
+ echo '</form>' . \PHP_EOL;
+ echo '</td>' . \PHP_EOL;
+
+ // Analyze
+ echo '<td style="text-align: center; vertical-align: bottom">' . \PHP_EOL;
+ echo '<form action="' . \containerInstance()->subFolder . "/src/views/{$script}\" method=\"post\">" . \PHP_EOL;
+ echo '<p><input type="hidden" name="action" value="confirm_analyze" />' . \PHP_EOL;
+ echo $this->view->form;
+ echo $table_hidden_inputs;
+ echo "<input type=\"submit\" value=\"{$this->lang['stranalyze']}\" /></p>" . \PHP_EOL;
+ echo '</form>' . \PHP_EOL;
+ echo '</td>' . \PHP_EOL;
+
+ // Cluster
+ echo $reclusterconf;
+
+ // Reindex
+ echo '<td style="text-align: center; vertical-align: bottom">' . \PHP_EOL;
+ echo '<form action="' . \containerInstance()->subFolder . "/src/views/{$script}\" method=\"post\">" . \PHP_EOL;
+ echo '<p><input type="hidden" name="action" value="confirm_reindex" />' . \PHP_EOL;
+ echo $this->view->form;
+ echo $table_hidden_inputs;
+ echo "<input type=\"submit\" value=\"{$this->lang['strreindex']}\" /></p>" . \PHP_EOL;
+ echo '</form>' . \PHP_EOL;
+ echo '</td>' . \PHP_EOL;
+ echo '</tr>' . \PHP_EOL;
+ echo '</table>' . \PHP_EOL;
+
+ if ($data) {
+ $this->_printAutoVacuumConf($data, $type);
+ }
+ }
+
+ /**
+ * @param mixed $action
+ * @param mixed $type
+ *
+ * @return bool
+ */
+ public function adminActions($action, $type)
+ {
+ if ('database' === $type) {
+ $_REQUEST['object'] = $_REQUEST['database'];
+ } else {
+ // $_REQUEST['table'] is no set if we are in the schema page
+ $_REQUEST['object'] = ($_REQUEST['table'] ?? '');
+
+ if (\is_array($_REQUEST['object'])) {
+ return false;
+ }
+ }
+
+ if (isset($_POST['cancel'])) {
+ $action = 'admin';
+ }
+
+ switch ($action) {
+ case 'admin':
+ $this->doAdmin($type);
+
+ break;
+ case 'confirm_cluster':
+ $this->confirmCluster($type);
+
+ break;
+ case 'confirm_reindex':
+ $this->confirmReindex($type);
+
+ break;
+ case 'confirm_analyze':
+ $this->confirmAnalyze($type);
+
+ break;
+ case 'confirm_vacuum':
+ $this->confirmVacuum($type);
+
+ break;
+ case 'confeditautovac':
+ $this->confirmEditAutovacuum($type);
+
+ break;
+ case 'confdelautovac':
+ $this->confirmDropAutovacuum($type);
+
+ break;
+ case 'cluster':
+ $this->doCluster($type);
+
+ break;
+ case 'reindex':
+ $this->doReindex($type);
+
+ break;
+ case 'analyze':
+ $this->doAnalyze($type);
+
+ break;
+ case 'vacuum':
+ $this->doVacuum($type);
+
+ break;
+ case 'editautovac':
+ $this->doEditAutovacuum($type);
+
+ break;
+ case 'delautovac':
+ $this->doDropAutovacuum($type);
+
+ break;
+
+ default:
+ return false;
+ }
+
+ return true;
+ }
+
+ abstract public function doDefault($msg = '');
+
+ /**
+ * Prints a trail.
+ *
+ * @param array|string $trail The trail
+ * @param bool $do_print The do print
+ *
+ * @return string ( description_of_the_return_value )
+ */
+ abstract public function printTrail($trail = [], bool $do_print = true);
+
+ abstract public function printTitle(string $title, ?string $help = null, bool $do_print = true);
+
+ abstract public function printMsg($msg, $do_print = true);
+
+ abstract public function printTabs(string $tabs, string $activetab, bool $do_print = true);
+
+ abstract public function printTable(IteratorAggregate &$tabledata, &$columns, &$actions, $place, $nodata = '', $pre_fn = null);
+
+ /**
+ * @psalm-return array{0: string, 1: string}
+ *
+ * @param mixed $data
+ * @param mixed $type
+ * @param mixed $table_hidden_inputs
+ *
+ * @return string[]
+ */
+ private function _getReclusterConf($data, $type, $table_hidden_inputs)
+ {
+ if (!$data->hasRecluster()) {
+ return ['', ''];
+ }
+ $script = $this->script;
+ $recluster_help = \sprintf(
+ '<th class="data">%s</th>',
+ $this->view->printHelp($this->lang['strclusterindex'], 'pg.index.cluster', false)
+ );
+
+ $disabled = '';
+ $reclusterconf = '<td style="text-align: center; vertical-align: bottom">' . \PHP_EOL;
+ $reclusterconf .= '<form action="' . \containerInstance()->subFolder . "/src/views/{$script}\" method=\"post\">" . \PHP_EOL;
+ $reclusterconf .= $this->view->form;
+ $reclusterconf .= $table_hidden_inputs;
+
+ if ('table' === $type && !$data->alreadyClustered($_REQUEST['object'])) {
+ $disabled = 'disabled="disabled" ';
+ $reclusterconf .= "{$this->lang['strnoclusteravailable']}<br />";
+ }
+ $reclusterconf .= '<p><input type="hidden" name="action" value="confirm_cluster" />' . \PHP_EOL;
+ $reclusterconf .= "<input type=\"submit\" value=\"{$this->lang['strclusterindex']}\" {$disabled}/></p>" . \PHP_EOL;
+ $reclusterconf .= '</form>' . \PHP_EOL;
+ $reclusterconf .= '</td>' . \PHP_EOL;
+
+ return [$recluster_help, $reclusterconf];
+ }
+
+ private function _printAutoVacuumConf(\PHPPgAdmin\Database\Postgres $data, $type): void
+ {
+ if (!$data->hasAutovacuum()) {
+ return;
+ }
+ $script = $this->script;
+ // get defaults values for autovacuum
+ $defaults = $data->getAutovacuum();
+ // Fetch the autovacuum properties from the database or table if != ''
+ if ('table' === $type) {
+ $autovac = $data->getTableAutovacuum($_REQUEST['table']);
+ } else {
+ $autovac = $data->getTableAutovacuum();
+ }
+
+ echo "<br /><br /><h2>{$this->lang['strvacuumpertable']}</h2>";
+ echo '<p>' . (('on' === $defaults['autovacuum']) ? $this->lang['strturnedon'] : $this->lang['strturnedoff']) . '</p>';
+ echo "<p class=\"message\">{$this->lang['strnotdefaultinred']}</p>";
+
+ $enlight = static function ($f, $p): string {
+ if (isset($f[$p[0]]) && ($f[$p[0]] !== $p[1])) {
+ return '<span style="color:#F33;font-weight:bold">' . \htmlspecialchars($f[$p[0]]) . '</span>';
+ }
+
+ return \htmlspecialchars($p[1]);
+ };
+
+ $columns = [
+ 'namespace' => [
+ 'title' => $this->lang['strschema'],
+ 'field' => Decorator::field('nspname'),
+ 'url' => \containerInstance()->getDestinationWithLastTab('schema'),
+ 'vars' => ['schema' => 'nspname'],
+ ],
+ 'relname' => [
+ 'title' => $this->lang['strtable'],
+ 'field' => Decorator::field('relname'),
+ 'url' => \containerInstance()->getDestinationWithLastTab('table'),
+ 'vars' => ['table' => 'relname', 'schema' => 'nspname'],
+ ],
+ 'autovacuum_enabled' => [
+ 'title' => $this->lang['strenabled'],
+ 'field' => Decorator::callback($enlight, ['autovacuum_enabled',
+ $defaults['autovacuum'], ]),
+ 'type' => 'verbatim',
+ ],
+ 'autovacuum_vacuum_threshold' => [
+ 'title' => $this->lang['strvacuumbasethreshold'],
+ 'field' => Decorator::callback($enlight, ['autovacuum_vacuum_threshold',
+ $defaults['autovacuum_vacuum_threshold'], ]),
+ 'type' => 'verbatim',
+ ],
+ 'autovacuum_vacuum_scale_factor' => [
+ 'title' => $this->lang['strvacuumscalefactor'],
+ 'field' => Decorator::callback($enlight, ['autovacuum_vacuum_scale_factor',
+ $defaults['autovacuum_vacuum_scale_factor'], ]),
+ 'type' => 'verbatim',
+ ],
+ 'autovacuum_analyze_threshold' => [
+ 'title' => $this->lang['stranalybasethreshold'],
+ 'field' => Decorator::callback($enlight, ['autovacuum_analyze_threshold',
+ $defaults['autovacuum_analyze_threshold'], ]),
+ 'type' => 'verbatim',
+ ],
+ 'autovacuum_analyze_scale_factor' => [
+ 'title' => $this->lang['stranalyzescalefactor'],
+ 'field' => Decorator::callback($enlight, ['autovacuum_analyze_scale_factor',
+ $defaults['autovacuum_analyze_scale_factor'], ]),
+ 'type' => 'verbatim',
+ ],
+ 'autovacuum_vacuum_cost_delay' => [
+ 'title' => $this->lang['strvacuumcostdelay'],
+ 'field' => Decorator::concat(Decorator::callback($enlight, ['autovacuum_vacuum_cost_delay',
+ $defaults['autovacuum_vacuum_cost_delay'], ]), 'ms'),
+ 'type' => 'verbatim',
+ ],
+ 'autovacuum_vacuum_cost_limit' => [
+ 'title' => $this->lang['strvacuumcostlimit'],
+ 'field' => Decorator::callback($enlight, ['autovacuum_vacuum_cost_limit',
+ $defaults['autovacuum_vacuum_cost_limit'], ]),
+ 'type' => 'verbatim',
+ ],
+ ];
+
+ // Maybe we need to check permissions here?
+ $columns['actions'] = ['title' => $this->lang['stractions']];
+
+ $actions = [
+ 'edit' => [
+ 'content' => $this->lang['stredit'],
+ 'attr' => [
+ 'href' => [
+ 'url' => $script,
+ 'urlvars' => [
+ 'subject' => $type,
+ 'action' => 'confeditautovac',
+ 'schema' => Decorator::field('nspname'),
+ 'table' => Decorator::field('relname'),
+ ],
+ ],
+ ],
+ ],
+ 'delete' => [
+ 'content' => $this->lang['strdelete'],
+ 'attr' => [
+ 'href' => [
+ 'url' => $script,
+ 'urlvars' => [
+ 'subject' => $type,
+ 'action' => 'confdelautovac',
+ 'schema' => Decorator::field('nspname'),
+ 'table' => Decorator::field('relname'),
+ ],
+ ],
+ ],
+ ],
+ ];
+
+ if ('table' === $type) {
+ unset(
+ $actions['edit']['attr']['href']['urlvars']['schema'], //$actions['edit']['vars']['schema'],
+ $actions['delete']['attr']['href']['urlvars']['schema'], //$actions['delete']['vars']['schema'],
+ $columns['namespace'],
+ $columns['relname']
+ );
+ }
+
+ if ($autovac instanceof \PHPPgAdmin\Core\ArrayRecordset) {
+ echo $this->printTable($autovac, $columns, $actions, 'admin-admin', $this->lang['strnovacuumconf']);
+ }
+
+ if (('table' === $type) && (0 === $autovac->RecordCount())) {
+ echo '<br />';
+
+ echo '<a href="' . \containerInstance()->subFolder . "/src/views/tables?action=confeditautovac&amp;{$this->misc->href}&amp;table=";
+ echo \htmlspecialchars($_REQUEST['table']);
+ echo "\">{$this->lang['straddvacuumtable']}</a>";
+ }
+ }
+}