action) { return $this->doTree(); } $header_template = 'header.twig'; ob_start(); switch ($this->action) { case 'alter': if (isset($_POST['alter'])) { $this->doSaveAlter(); } else { $this->doDefault(); } break; case 'confirm_alter': $this->doAlter(); break; case 'import': $this->doImport(); break; case 'export': $this->doExport(); break; case 'add_column': if (isset($_POST['cancel'])) { $this->doDefault(); } else { $header_template = 'header_select2.twig'; $this->doAddColumn(); } break; /*case 'properties': if (isset($_POST['cancel'])) { $this->doDefault(); } else { $this->doProperties(); }*/ break; case 'drop': if (isset($_POST['drop'])) { $this->doDrop(false); } else { $this->doDefault(); } break; case 'confirm_drop': $this->doDrop(true); break; default: $this->doDefault(); break; } $output = ob_get_clean(); $this->printHeader($this->headerTitle('', '', $_REQUEST['table']), null, true, $header_template); $this->printBody(); echo $output; return $this->printFooter(); } /** * Show default list of columns in the table. * * @param mixed $msg */ public function doDefault($msg = '') { $misc = $this->misc; $this->data = $misc->getDatabaseAccessor(); $this->printTrail('table'); $this->printTabs('table', 'columns'); $this->printMsg($msg); // Get table $tdata = $this->data->getTable($_REQUEST['table']); // Get columns $attrs = $this->data->getTableAttributes($_REQUEST['table']); // Get constraints keys $ck = $this->data->getConstraintsWithFields($_REQUEST['table']); // Show comment if any if (null !== $tdata->fields['relcomment']) { echo '

', $misc->printVal($tdata->fields['relcomment']), '

'.PHP_EOL; } $this->_printTable($ck, $attrs); $navlinks = [ 'browse' => [ 'attr' => [ 'href' => [ 'url' => 'display', 'urlvars' => [ 'server' => $_REQUEST['server'], 'database' => $_REQUEST['database'], 'schema' => $_REQUEST['schema'], 'table' => $_REQUEST['table'], 'subject' => 'table', 'return' => 'table', ], ], ], 'content' => $this->lang['strbrowse'], ], 'select' => [ 'attr' => [ 'href' => [ 'url' => 'tables', 'urlvars' => [ 'action' => 'confselectrows', 'server' => $_REQUEST['server'], 'database' => $_REQUEST['database'], 'schema' => $_REQUEST['schema'], 'table' => $_REQUEST['table'], ], ], ], 'content' => $this->lang['strselect'], ], 'insert' => [ 'attr' => [ 'href' => [ 'url' => 'tables', 'urlvars' => [ 'action' => 'confinsertrow', 'server' => $_REQUEST['server'], 'database' => $_REQUEST['database'], 'schema' => $_REQUEST['schema'], 'table' => $_REQUEST['table'], ], ], ], 'content' => $this->lang['strinsert'], ], 'empty' => [ 'attr' => [ 'href' => [ 'url' => 'tables', 'urlvars' => [ 'action' => 'confirm_empty', 'server' => $_REQUEST['server'], 'database' => $_REQUEST['database'], 'schema' => $_REQUEST['schema'], 'table' => $_REQUEST['table'], ], ], ], 'content' => $this->lang['strempty'], ], 'drop' => [ 'attr' => [ 'href' => [ 'url' => 'tables', 'urlvars' => [ 'action' => 'confirm_drop', 'server' => $_REQUEST['server'], 'database' => $_REQUEST['database'], 'schema' => $_REQUEST['schema'], 'table' => $_REQUEST['table'], ], ], ], 'content' => $this->lang['strdrop'], ], 'addcolumn' => [ 'attr' => [ 'href' => [ 'url' => 'tblproperties', 'urlvars' => [ 'action' => 'add_column', 'server' => $_REQUEST['server'], 'database' => $_REQUEST['database'], 'schema' => $_REQUEST['schema'], 'table' => $_REQUEST['table'], ], ], ], 'content' => $this->lang['straddcolumn'], ], 'alter' => [ 'attr' => [ 'href' => [ 'url' => 'tblproperties', 'urlvars' => [ 'action' => 'confirm_alter', 'server' => $_REQUEST['server'], 'database' => $_REQUEST['database'], 'schema' => $_REQUEST['schema'], 'table' => $_REQUEST['table'], ], ], ], 'content' => $this->lang['stralter'], ], ]; $this->printNavLinks($navlinks, 'tblproperties-tblproperties', get_defined_vars()); } public function doTree() { $misc = $this->misc; $data = $misc->getDatabaseAccessor(); $columns = $data->getTableAttributes($_REQUEST['table']); $reqvars = $misc->getRequestVars('column'); $attrs = [ 'text' => Decorator::field('attname'), 'action' => Decorator::actionurl( 'colproperties', $reqvars, [ 'table' => $_REQUEST['table'], 'column' => Decorator::field('attname'), ] ), 'icon' => 'Column', 'iconAction' => Decorator::url( 'display', $reqvars, [ 'table' => $_REQUEST['table'], 'column' => Decorator::field('attname'), 'query' => Decorator::replace( 'SELECT "%column%", count(*) AS "count" FROM "%table%" GROUP BY "%column%" ORDER BY "%column%"', [ '%column%' => Decorator::field('attname'), '%table%' => $_REQUEST['table'], ] ), ] ), 'toolTip' => Decorator::field('comment'), ]; return $this->printTree($columns, $attrs, 'tblcolumns'); } public function doSaveAlter() { $misc = $this->misc; $data = $misc->getDatabaseAccessor(); // For databases that don't allow owner change $this->coalesceArr($_POST, 'owner', ''); // Default tablespace to null if it isn't set $this->coalesceArr($_POST, 'tablespace', null); $this->coalesceArr($_POST, 'newschema', null); $status = $data->alterTable($_POST['table'], $_POST['name'], $_POST['owner'], $_POST['newschema'], $_POST['comment'], $_POST['tablespace']); if (0 == $status) { // If table has been renamed, need to change to the new name and // reload the browser frame. if ($_POST['table'] != $_POST['name']) { // Jump them to the new table name $_REQUEST['table'] = $_POST['name']; // Force a browser reload $misc->setReloadBrowser(true); } // If schema has changed, need to change to the new schema and reload the browser if (!empty($_POST['newschema']) && ($_POST['newschema'] != $data->_schema)) { // Jump them to the new sequence schema $misc->setCurrentSchema($_POST['newschema']); $misc->setReloadBrowser(true); } $this->doDefault($this->lang['strtablealtered']); } else { $this->doAlter($this->lang['strtablealteredbad']); } } /** * Function to allow altering of a table. * * @param mixed $msg */ public function doAlter($msg = '') { $misc = $this->misc; $data = $misc->getDatabaseAccessor(); $this->printTrail('table'); $this->printTitle($this->lang['stralter'], 'pg.table.alter'); $this->printMsg($msg); // Fetch table info $table = $data->getTable($_REQUEST['table']); // Fetch all users $users = $data->getUsers(); $tablespaces = null; // Fetch all tablespaces from the database if ($data->hasTablespaces()) { $tablespaces = $data->getTablespaces(true); } if ($table->recordCount() > 0) { $this->coalesceArr($_POST, 'name', $table->fields['relname']); $this->coalesceArr($_POST, 'owner', $table->fields['relowner']); $this->coalesceArr($_POST, 'newschema', $table->fields['nspname']); $this->coalesceArr($_POST, 'comment', $table->fields['relcomment']); if ($data->hasTablespaces() && !isset($_POST['tablespace'])) { $_POST['tablespace'] = $table->fields['tablespace']; } echo '
'.PHP_EOL; echo ''.PHP_EOL; echo "".PHP_EOL; echo ''.PHP_EOL; if ($data->isSuperUser()) { echo "".PHP_EOL; echo ''.PHP_EOL; } if ($data->hasAlterTableSchema()) { $schemas = $data->getSchemas(); echo "".PHP_EOL; echo ''.PHP_EOL; } // Tablespace (if there are any) if ($data->hasTablespaces() && $tablespaces->recordCount() > 0) { echo "\t\n\t\t".PHP_EOL; echo "\t\t\n\t".PHP_EOL; } echo "".PHP_EOL; echo ''.PHP_EOL; echo '
{$this->lang['strname']}'; echo "_maxNameLen}\" value=\"", htmlspecialchars($_POST['name'], ENT_QUOTES), '" />
{$this->lang['strowner']}
{$this->lang['strschema']}
{$this->lang['strtablespace']}\n\t\t\t\n\t\t
{$this->lang['strcomment']}'; echo '
'.PHP_EOL; echo '

'.PHP_EOL; echo ''.PHP_EOL; echo $misc->form; echo "lang['stralter']}\" />".PHP_EOL; echo "lang['strcancel']}\" />

".PHP_EOL; echo '
'.PHP_EOL; } else { echo "

{$this->lang['strnodata']}

".PHP_EOL; } } public function doExport($msg = '') { $data = $this->misc->getDatabaseAccessor(); $subject = 'table'; $object = $_REQUEST['table']; // Determine whether or not the table has an object ID $hasID = $data->hasObjectID($object); $this->prtrace('$hasID', $hasID); $this->printTrail('table'); $this->printTabs('table', 'export'); $this->printMsg($msg); echo $this->formHeader(); // Data only echo $this->dataOnly($hasID); // Structure only echo $this->structureOnly(); // Structure and data echo $this->structureAndData($hasID); echo $this->displayOrDownload(); echo $this->formFooter($subject, $object); } public function doImport($msg = '') { $misc = $this->misc; $this->printTrail('table'); $this->printTabs('table', 'import'); $this->printMsg($msg); // Check that file uploads are enabled if (!ini_get('file_uploads')) { echo "

{$this->lang['strnouploads']}

".PHP_EOL; return; } // Don't show upload option if max size of uploads is zero $max_size = $misc->inisizeToBytes(ini_get('upload_max_filesize')); if (is_double($max_size) && $max_size > 0) { echo '
'.PHP_EOL; echo ''.PHP_EOL; echo "\t\n\t\t".PHP_EOL; echo "\t\t\n\t".PHP_EOL; echo "\t\n\t\t".PHP_EOL; echo "\t\t\n\t".PHP_EOL; echo "\t\n\t\t".PHP_EOL; echo "\t\t\n\t".PHP_EOL; echo '
{$this->lang['strformat']}
{$this->lang['strallowednulls']}
".PHP_EOL; echo "\t\t
".PHP_EOL; echo "\t\t
{$this->lang['strfile']}"; echo "
'.PHP_EOL; echo '

'.PHP_EOL; echo $misc->form; echo ''.PHP_EOL; echo "lang['strimport']}\" />

".PHP_EOL; echo '
'.PHP_EOL; } } /** * Displays a screen where they can add a column. * * @param mixed $msg */ public function doAddColumn($msg = '') { $misc = $this->misc; $data = $misc->getDatabaseAccessor(); $this->coalesceArr($_REQUEST, 'stage', 1); switch ($_REQUEST['stage']) { case 1: // Set variable defaults $this->coalesceArr($_POST, 'field', ''); $this->coalesceArr($_POST, 'type', ''); $this->coalesceArr($_POST, 'array', ''); $this->coalesceArr($_POST, 'length', ''); $this->coalesceArr($_POST, 'default', ''); $this->coalesceArr($_POST, 'comment', ''); // Fetch all available types $types = $data->getTypes(true, false, true); $types_for_js = []; $this->printTrail('table'); $this->printTitle($this->lang['straddcolumn'], 'pg.column.add'); $this->printMsg($msg); echo ''; echo '
'.PHP_EOL; // Output table header echo ''.PHP_EOL; echo "\n".PHP_EOL; echo "".PHP_EOL; if ($data->hasCreateFieldWithConstraints()) { echo "\n".PHP_EOL; } echo "".PHP_EOL; echo "'.PHP_EOL; echo "'.PHP_EOL; // Output array type selector echo ''.PHP_EOL; $predefined_size_types = array_intersect($data->predefined_size_types, $types_for_js); $escaped_predef_types = []; // the JS escaped array elements foreach ($predefined_size_types as $value) { $escaped_predef_types[] = "'{$value}'"; } echo ''.PHP_EOL; // Support for adding column with not null and default if ($data->hasCreateFieldWithConstraints()) { echo ''.PHP_EOL; echo ''.PHP_EOL; } echo ''.PHP_EOL; echo '
{$this->lang['strname']}{$this->lang['strtype']}{$this->lang['strlength']}{$this->lang['strnotnull']}{$this->lang['strdefault']}{$this->lang['strcomment']}
_maxNameLen}\" value=\"", htmlspecialchars($_POST['field']), '" />
'.PHP_EOL; echo '

'.PHP_EOL; echo ''.PHP_EOL; echo $misc->form; echo ''.PHP_EOL; if (!$data->hasCreateFieldWithConstraints()) { echo ''.PHP_EOL; } echo "lang['stradd']}\" />".PHP_EOL; echo "lang['strcancel']}\" />

".PHP_EOL; echo '
'.PHP_EOL; echo '".PHP_EOL; break; case 2: // Check inputs if ('' == trim($_POST['field'])) { $_REQUEST['stage'] = 1; $this->doAddColumn($this->lang['strcolneedsname']); return; } $this->coalesceArr($_POST, 'length', ''); list($status, $sql) = $data->addColumn( $_POST['table'], $_POST['field'], $_POST['type'], '' != $_POST['array'], $_POST['length'], isset($_POST['notnull']), $_POST['default'], $_POST['comment'] ); if (0 == $status) { $misc->setReloadBrowser(true); $this->doDefault(sprintf('%s %s %s', $sql, PHP_EOL, $this->lang['strcolumnadded'])); } else { $_REQUEST['stage'] = 1; $this->doAddColumn($this->lang['strcolumnaddedbad']); return; } break; default: echo "

{$this->lang['strinvalidparam']}

".PHP_EOL; } } /** * Show confirmation of drop column and perform actual drop. * * @param bool $confirm true to ask for confirmation, false to actually drop */ public function doDrop($confirm = true) { $misc = $this->misc; $data = $misc->getDatabaseAccessor(); if ($confirm) { $this->printTrail('column'); $this->printTitle($this->lang['strdrop'], 'pg.column.drop'); echo '

'.sprintf($this->lang['strconfdropcolumn'], $misc->printVal($_REQUEST['column']), $misc->printVal($_REQUEST['table'])).'

'.PHP_EOL; echo '
'.PHP_EOL; echo ''.PHP_EOL; echo ''.PHP_EOL; echo ''.PHP_EOL; echo $misc->form; echo "

".PHP_EOL; echo "lang['strdrop']}\" />".PHP_EOL; echo "lang['strcancel']}\" />".PHP_EOL; echo '
'.PHP_EOL; } else { list($status, $sql) = $data->dropColumn($_POST['table'], $_POST['column'], isset($_POST['cascade'])); if (0 == $status) { $misc->setReloadBrowser(true); $this->doDefault(sprintf('%s %s %s', $sql, PHP_EOL, $this->lang['strcolumndropped'])); } else { $this->doDefault($this->lang['strcolumndroppedbad']); } } } private function _getAttPre($data) { $attPre = function (&$rowdata, $actions) use ($data) { $rowdata->fields['+type'] = $data->formatType($rowdata->fields['type'], $rowdata->fields['atttypmod']); $attname = $rowdata->fields['attname']; $table = $_REQUEST['table']; $data->fieldClean($attname); $data->fieldClean($table); $actions['browse']['attr']['href']['urlvars']['query'] = "SELECT \"{$attname}\", count(*) AS \"count\" FROM \"{$table}\" GROUP BY \"{$attname}\" ORDER BY \"{$attname}\""; return $actions; }; return $attPre; } private function _getCstrRender($misc, $data) { $cstrRender = function ($s, $p) use ($misc, $data) { $str = ''; foreach ($p['keys'] as $k => $c) { if (is_null($p['keys'][$k]['consrc'])) { $atts = $data->getAttributeNames($_REQUEST['table'], explode(' ', $p['keys'][$k]['indkey'])); $c['consrc'] = ('u' == $c['contype'] ? 'UNIQUE (' : 'PRIMARY KEY (').join(',', $atts).')'; } if ($c['p_field'] == $s) { switch ($c['contype']) { case 'p': $str .= '[pk]'; break; case 'f': $str .= '[fk]'; break; case 'u': $str .= '[uniq]'; break; case 'c': $str .= '[check]'; } } } return $str; }; return $cstrRender; } private function _printTable($ck, $attrs) { $misc = $this->misc; $data = $this->data; $attPre = $this->_getAttPre($data); $cstrRender = $this->_getCstrRender($misc, $data); $columns = [ 'column' => [ 'title' => $this->lang['strcolumn'], 'field' => Decorator::field('attname'), 'url' => "colproperties?subject=column&{$misc->href}&table=".urlencode($_REQUEST['table']).'&', 'vars' => ['column' => 'attname'], ], 'type' => [ 'title' => $this->lang['strtype'], 'field' => Decorator::field('+type'), ], 'notnull' => [ 'title' => $this->lang['strnotnull'], 'field' => Decorator::field('attnotnull'), 'type' => 'bool', 'params' => ['true' => 'NOT NULL', 'false' => ''], ], 'default' => [ 'title' => $this->lang['strdefault'], 'field' => Decorator::field('adsrc'), ], 'keyprop' => [ 'title' => $this->lang['strconstraints'], 'class' => 'constraint_cell', 'field' => Decorator::field('attname'), 'type' => 'callback', 'params' => [ 'function' => $cstrRender, 'keys' => $ck->getArray(), ], ], 'actions' => [ 'title' => $this->lang['stractions'], ], 'comment' => [ 'title' => $this->lang['strcomment'], 'field' => Decorator::field('comment'), ], ]; $actions = [ 'browse' => [ 'content' => $this->lang['strbrowse'], 'attr' => [ 'href' => [ 'url' => 'display', 'urlvars' => [ 'table' => $_REQUEST['table'], 'subject' => 'column', 'return' => 'table', 'column' => Decorator::field('attname'), ], ], ], ], 'alter' => [ 'content' => $this->lang['stralter'], 'attr' => [ 'href' => [ 'url' => 'colproperties', 'urlvars' => [ 'subject' => 'column', 'action' => 'properties', 'table' => $_REQUEST['table'], 'column' => Decorator::field('attname'), ], ], ], ], 'privileges' => [ 'content' => $this->lang['strprivileges'], 'attr' => [ 'href' => [ 'url' => 'privileges', 'urlvars' => [ 'subject' => 'column', 'table' => $_REQUEST['table'], 'column' => Decorator::field('attname'), ], ], ], ], 'drop' => [ 'content' => $this->lang['strdrop'], 'attr' => [ 'href' => [ 'url' => 'tblproperties', 'urlvars' => [ 'subject' => 'column', 'action' => 'confirm_drop', 'table' => $_REQUEST['table'], 'column' => Decorator::field('attname'), ], ], ], ], ]; echo $this->printTable($attrs, $columns, $actions, 'tblproperties-tblproperties', $this->lang['strnodata'], $attPre); } }