action) { return $this->doTree(); } if ('subtree' == $this->action) { return $this->doSubTree(); } if ('json' == $this->action) { return $this->displayJson(); } $header_template = 'header.twig'; ob_start(); switch ($this->action) { case 'create': if (isset($_POST['cancel'])) { $this->doDefault(); } else { $header_template = 'header_select2.twig'; $this->doCreate(); } break; case 'createlike': $header_template = 'header_select2.twig'; $this->doCreateLike(false); break; case 'confcreatelike': if (isset($_POST['cancel'])) { $header_template = 'header_datatables.twig'; $this->doDefault(); } else { //$header_template = 'header_select2.twig'; $this->doCreateLike(true); } break; case 'selectrows': if (!isset($_POST['cancel'])) { $this->doSelectRows(false); } else { $header_template = 'header_datatables.twig'; $this->doDefault(); } break; case 'confselectrows': $this->doSelectRows(true); break; case 'insertrow': if (!isset($_POST['cancel'])) { $this->doInsertRow(); } else { $header_template = 'header_datatables.twig'; $this->doDefault(); } break; case 'confinsertrow': $this->formInsertRow(); break; case 'empty': if (isset($_POST['empty'])) { $this->doEmpty(false); } else { $header_template = 'header_datatables.twig'; $this->doDefault(); } break; case 'confirm_empty': $this->doEmpty(true); break; case 'drop': if (isset($_POST['drop'])) { $this->doDrop(false); } else { $header_template = 'header_datatables.twig'; $this->doDefault(); } break; case 'confirm_drop': $this->doDrop(true); break; default: if (false === $this->adminActions($this->action, 'table')) { $header_template = 'header_datatables.twig'; $this->doDefault(); } break; } $output = ob_get_clean(); $this->printHeader($this->headerTitle(), null, true, $header_template); $this->printBody(); echo $output; return $this->printFooter(); } private function _getColumns() { $columns = [ 'table' => [ 'title' => $this->lang['strtable'], 'field' => Decorator::field('relname'), 'url' => \SUBFOLDER."/redirect/table?{$this->misc->href}&", 'vars' => ['table' => 'relname'], ], 'owner' => [ 'title' => $this->lang['strowner'], 'field' => Decorator::field('relowner'), ], 'tablespace' => [ 'title' => $this->lang['strtablespace'], 'field' => Decorator::field('tablespace'), ], 'tuples' => [ 'title' => $this->lang['strestimatedrowcount'], 'field' => Decorator::field('reltuples'), 'type' => 'numeric', ], 'table_size' => [ 'title' => $this->lang['strsize'], 'field' => Decorator::field('table_size'), ], 'actions' => [ 'title' => $this->lang['stractions'], ], 'comment' => [ 'title' => $this->lang['strcomment'], 'field' => Decorator::field('relcomment'), ], ]; return $columns; } private function _getActions() { $actions = [ 'multiactions' => [ 'keycols' => ['table' => 'relname'], 'url' => 'tables', 'default' => 'analyze', ], 'browse' => [ 'content' => $this->lang['strbrowse'], 'attr' => [ 'href' => [ 'url' => 'display', 'urlvars' => [ 'subject' => 'table', 'return' => 'table', 'table' => Decorator::field('relname'), ], ], ], ], 'select' => [ 'content' => $this->lang['strselect'], 'attr' => [ 'href' => [ 'url' => 'tables', 'urlvars' => [ 'action' => 'confselectrows', 'table' => Decorator::field('relname'), ], ], ], ], 'insert' => [ 'content' => $this->lang['strinsert'], 'attr' => [ 'href' => [ 'url' => 'tables', 'urlvars' => [ 'action' => 'confinsertrow', 'table' => Decorator::field('relname'), ], ], ], ], 'empty' => [ 'multiaction' => 'confirm_empty', 'content' => $this->lang['strempty'], 'attr' => [ 'href' => [ 'url' => 'tables', 'urlvars' => [ 'action' => 'confirm_empty', 'table' => Decorator::field('relname'), ], ], ], ], 'alter' => [ 'content' => $this->lang['stralter'], 'attr' => [ 'href' => [ 'url' => 'tblproperties', 'urlvars' => [ 'action' => 'confirm_alter', 'table' => Decorator::field('relname'), ], ], ], ], 'drop' => [ 'multiaction' => 'confirm_drop', 'content' => $this->lang['strdrop'], 'attr' => [ 'href' => [ 'url' => 'tables', 'urlvars' => [ 'action' => 'confirm_drop', 'table' => Decorator::field('relname'), ], ], ], ], 'vacuum' => [ 'multiaction' => 'confirm_vacuum', 'content' => $this->lang['strvacuum'], 'attr' => [ 'href' => [ 'url' => 'tables', 'urlvars' => [ 'action' => 'confirm_vacuum', 'table' => Decorator::field('relname'), ], ], ], ], 'analyze' => [ 'multiaction' => 'confirm_analyze', 'content' => $this->lang['stranalyze'], 'attr' => [ 'href' => [ 'url' => 'tables', 'urlvars' => [ 'action' => 'confirm_analyze', 'table' => Decorator::field('relname'), ], ], ], ], 'reindex' => [ 'multiaction' => 'confirm_reindex', 'content' => $this->lang['strreindex'], 'attr' => [ 'href' => [ 'url' => 'tables', 'urlvars' => [ 'action' => 'confirm_reindex', 'table' => Decorator::field('relname'), ], ], ], ], //'cluster' TODO ? ]; return $actions; } /** * Show default list of tables in the database. * * @param mixed $msg */ public function doDefault($msg = '') { $data = $this->misc->getDatabaseAccessor(); $this->printTrail('schema'); $this->printTabs('schema', 'tables'); $this->printMsg($msg); $tables = $data->getTables(); $columns = $this->_getColumns(); $actions = $this->_getActions(); //\Kint::dump($tables); echo $this->printTable($tables, $columns, $actions, $this->table_place, $this->lang['strnotables']); $navlinks = [ 'create' => [ 'attr' => [ 'href' => [ 'url' => 'tables', 'urlvars' => [ 'action' => 'create', 'server' => $_REQUEST['server'], 'database' => $_REQUEST['database'], 'schema' => $_REQUEST['schema'], ], ], ], 'content' => $this->lang['strcreatetable'], ], ]; if (($tables->recordCount() > 0) && $data->hasCreateTableLike()) { $navlinks['createlike'] = [ 'attr' => [ 'href' => [ 'url' => 'tables', 'urlvars' => [ 'action' => 'createlike', 'server' => $_REQUEST['server'], 'database' => $_REQUEST['database'], 'schema' => $_REQUEST['schema'], ], ], ], 'content' => $this->lang['strcreatetablelike'], ]; } $this->printNavLinks($navlinks, 'tables-tables', get_defined_vars()); } public function displayJson() { $data = $this->misc->getDatabaseAccessor(); $tables = $data->getTables(); $all_tables = $tables->getAll(); return $this ->container ->responseobj ->withStatus(200) ->withJson($all_tables); } /** * Generate XML for the browser tree. */ public function doTree() { $data = $this->misc->getDatabaseAccessor(); $tables = $data->getTables(); $reqvars = $this->misc->getRequestVars('table'); $attrs = [ 'text' => Decorator::field('relname'), 'icon' => 'Table', 'iconAction' => Decorator::url('display', $reqvars, ['table' => Decorator::field('relname')]), 'toolTip' => Decorator::field('relcomment'), 'action' => Decorator::redirecturl('redirect', $reqvars, ['table' => Decorator::field('relname')]), 'branch' => Decorator::url('tables', $reqvars, ['action' => 'subtree', 'table' => Decorator::field('relname')]), ]; return $this->printTree($tables, $attrs, 'tables'); } public function doSubTree() { $tabs = $this->misc->getNavTabs('table'); $items = $this->adjustTabsForTree($tabs); $reqvars = $this->misc->getRequestVars('table'); $attrs = [ 'text' => Decorator::field('title'), 'icon' => Decorator::field('icon'), 'action' => Decorator::actionurl( Decorator::field('url'), $reqvars, Decorator::field('urlvars'), ['table' => $_REQUEST['table']] ), 'branch' => Decorator::ifempty( Decorator::field('branch'), '', Decorator::url( Decorator::field('url'), $reqvars, [ 'action' => 'tree', 'table' => $_REQUEST['table'], ] ) ), ]; return $this->printTree($items, $attrs, 'table'); } /** * Displays a screen where they can enter a new table. * * @param mixed $msg */ public function doCreate($msg = '') { $data = $this->misc->getDatabaseAccessor(); if (!isset($_REQUEST['stage'])) { $_REQUEST['stage'] = 1; $default_with_oids = $data->getDefaultWithOid(); if ('off' == $default_with_oids) { $_REQUEST['withoutoids'] = 'on'; } } $this->coalesceArr($_REQUEST, 'name', ''); $this->coalesceArr($_REQUEST, 'fields', ''); $this->coalesceArr($_REQUEST, 'tblcomment', ''); $this->coalesceArr($_REQUEST, 'spcname', ''); $tablespaces = null; switch ($_REQUEST['stage']) { case 1: // You are presented with a form in which you describe the table, pick the tablespace and state how many fields it will have // Fetch all tablespaces from the database if ($data->hasTablespaces()) { $tablespaces = $data->getTablespaces(); } $this->printTrail('schema'); $this->printTitle($this->lang['strcreatetable'], 'pg.table.create'); $this->printMsg($msg); echo '
'.PHP_EOL; break; case 2: // Check inputs $fields = trim($_REQUEST['fields']); if ('' == trim($_REQUEST['name'])) { $_REQUEST['stage'] = 1; $this->doCreate($this->lang['strtableneedsname']); return; } if ('' == $fields || !is_numeric($fields) || $fields != (int) $fields || $fields < 1) { $_REQUEST['stage'] = 1; $this->doCreate($this->lang['strtableneedscols']); return; } $types = $data->getTypes(true, false, true); $types_for_js = []; $this->printTrail('schema'); $this->printTitle($this->lang['strcreatetable'], 'pg.table.create'); $this->printMsg($msg); echo ''; echo ''.PHP_EOL; break; case 3: $this->coalesceArr($_REQUEST, 'notnull', []); $this->coalesceArr($_REQUEST, 'uniquekey', []); $this->coalesceArr($_REQUEST, 'primarykey', []); $this->coalesceArr($_REQUEST, 'length', []); // Default tablespace to null if it isn't set $this->coalesceArr($_REQUEST, 'spcname', null); // Check inputs $fields = trim($_REQUEST['fields']); if ('' == trim($_REQUEST['name'])) { $_REQUEST['stage'] = 1; $this->doCreate($this->lang['strtableneedsname']); return; } if ('' == $fields || !is_numeric($fields) || $fields != (int) $fields || $fields <= 0) { $_REQUEST['stage'] = 1; $this->doCreate($this->lang['strtableneedscols']); return; } $status = $data->createTable( $_REQUEST['name'], $_REQUEST['fields'], $_REQUEST['field'], $_REQUEST['type'], $_REQUEST['array'], $_REQUEST['length'], $_REQUEST['notnull'], $_REQUEST['default'], isset($_REQUEST['withoutoids']), $_REQUEST['colcomment'], $_REQUEST['tblcomment'], $_REQUEST['spcname'], $_REQUEST['uniquekey'], $_REQUEST['primarykey'] ); if (0 == $status) { $this->misc->setReloadBrowser(true); return $this->doDefault($this->lang['strtablecreated']); } if ($status == -1) { $_REQUEST['stage'] = 2; $this->doCreate($this->lang['strtableneedsfield']); return; } $_REQUEST['stage'] = 2; $this->doCreate($this->lang['strtablecreatedbad']); return; break; default: echo "{$this->lang['strinvalidparam']}
".PHP_EOL; } } /** * Dsiplay a screen where user can create a table from an existing one. * We don't have to check if pg supports schema cause create table like * is available under pg 7.4+ which has schema. * * @param mixed $confirm * @param mixed $msg */ public function doCreateLike($confirm, $msg = '') { $data = $this->misc->getDatabaseAccessor(); if (!$confirm) { $this->coalesceArr($_REQUEST, 'name', ''); $this->coalesceArr($_REQUEST, 'like', ''); $this->coalesceArr($_REQUEST, 'tablespace', ''); $this->printTrail('schema'); $this->printTitle($this->lang['strcreatetable'], 'pg.table.create'); $this->printMsg($msg); $tbltmp = $data->getAllTables(); $tbltmp = $tbltmp->getArray(); $tables = []; $tblsel = ''; foreach ($tbltmp as $a) { $data->fieldClean($a['nspname']); $data->fieldClean($a['relname']); $tables["\"{$a['nspname']}\".\"{$a['relname']}\""] = serialize(['schema' => $a['nspname'], 'table' => $a['relname']]); if ($_REQUEST['like'] == $tables["\"{$a['nspname']}\".\"{$a['relname']}\""]) { $tblsel = htmlspecialchars($tables["\"{$a['nspname']}\".\"{$a['relname']}\""]); } } unset($tbltmp); echo ''.PHP_EOL; } else { if ('' == trim($_REQUEST['name'])) { $this->doCreateLike(false, $this->lang['strtableneedsname']); return; } if ('' == trim($_REQUEST['like'])) { $this->doCreateLike(false, $this->lang['strtablelikeneedslike']); return; } $this->coalesceArr($_REQUEST, 'tablespace', ''); $status = $data->createTableLike( $_REQUEST['name'], unserialize($_REQUEST['like']), isset($_REQUEST['withdefaults']), isset($_REQUEST['withconstraints']), isset($_REQUEST['withindexes']), $_REQUEST['tablespace'] ); if (0 == $status) { $this->misc->setReloadBrowser(true); return $this->doDefault($this->lang['strtablecreated']); } $this->doCreateLike(false, $this->lang['strtablecreatedbad']); return; } } /** * Ask for select parameters and perform select. * * @param mixed $confirm * @param mixed $msg */ public function doSelectRows($confirm, $msg = '') { $data = $this->misc->getDatabaseAccessor(); if ($confirm) { $this->printTrail('table'); $this->printTabs('table', 'select'); $this->printMsg($msg); $attrs = $data->getTableAttributes($_REQUEST['table']); echo ''.PHP_EOL; return; } $this->coalesceArr($_POST, 'show', []); $this->coalesceArr($_POST, 'values', []); $this->coalesceArr($_POST, 'nulls', []); // Verify that they haven't supplied a value for unary operators foreach ($_POST['ops'] as $k => $v) { if ('p' == $data->selectOps[$v] && $_POST['values'][$k] != '') { $this->doSelectRows(true, $this->lang['strselectunary']); return; } } if (0 == sizeof($_POST['show'])) { $this->doSelectRows(true, $this->lang['strselectneedscol']); } else { // Generate query SQL $query = $data->getSelectSQL( $_REQUEST['table'], array_keys($_POST['show']), $_POST['values'], $_POST['ops'] ); $_REQUEST['query'] = $query; $_REQUEST['return'] = 'selectrows'; $this->setNoOutput(true); $display_controller = new DisplayController($this->getContainer()); return $display_controller->render(); } } /** * Ask for insert parameters and then actually insert row. * * @param mixed $msg */ public function formInsertRow($msg = '') { $data = $this->misc->getDatabaseAccessor(); $this->printTrail('table'); $this->printTabs('table', 'insert'); $this->printMsg($msg); $attrs = $data->getTableAttributes($_REQUEST['table']); $fksprops = $this->_getFKProps(); $this->coalesceArr($_REQUEST, 'values', []); $this->coalesceArr($_REQUEST, 'nulls', []); $this->coalesceArr($_REQUEST, 'format', []); echo ''.PHP_EOL; echo ''; } /** * Performs insertion of row according to request parameters. */ public function doInsertRow() { $data = $this->misc->getDatabaseAccessor(); $this->coalesceArr($_POST, 'values', []); $this->coalesceArr($_POST, 'nulls', []); $_POST['fields'] = unserialize(htmlspecialchars_decode($_POST['fields'], ENT_QUOTES)); if ($_SESSION['counter']++ == $_POST['protection_counter']) { $status = $data->insertRow($_POST['table'], $_POST['fields'], $_POST['values'], $_POST['nulls'], $_POST['format'], $_POST['types']); if (0 == $status) { if (isset($_POST['insert'])) { return $this->doDefault($this->lang['strrowinserted']); } $_REQUEST['values'] = []; $_REQUEST['nulls'] = []; return $this->formInsertRow($this->lang['strrowinserted']); } return $this->formInsertRow($this->lang['strrowinsertedbad']); } return $this->formInsertRow($this->lang['strrowduplicate']); } /** * Show confirmation of empty and perform actual empty. * * @param mixed $confirm */ public function doEmpty($confirm) { $data = $this->misc->getDatabaseAccessor(); if (empty($_REQUEST['table']) && empty($_REQUEST['ma'])) { return $this->doDefault($this->lang['strspecifytabletoempty']); } if ($confirm) { if (isset($_REQUEST['ma'])) { $this->printTrail('schema'); $this->printTitle($this->lang['strempty'], 'pg.table.empty'); echo '\n"; // END if confirm } else { // Do Empty $msg = ''; if (is_array($_REQUEST['table'])) { foreach ($_REQUEST['table'] as $t) { list($status, $sql) = $data->emptyTable($t, isset($_POST['cascade'])); if (0 == $status) { $msg .= sprintf('%s