misc = $this->misc;
$plugin_manager = $this->plugin_manager;
if ('dobrowsefk' == $this->action) {
return $this->doBrowseFK();
}
set_time_limit(0);
$scripts = '';
$scripts .= ''.PHP_EOL;
$footer_template = 'footer.twig';
$header_template = 'header.twig';
ob_start();
switch ($this->action) {
case 'editrow':
$header_template = 'header_sqledit.twig';
$footer_template = 'footer_sqledit.twig';
if (isset($_POST['save'])) {
$this->doEditRow();
} else {
$this->doBrowse();
}
break;
case 'confeditrow':
$this->formEditRow();
break;
case 'delrow':
$header_template = 'header_sqledit.twig';
$footer_template = 'footer_sqledit.twig';
if (isset($_POST['yes'])) {
$this->doDelRow(false);
} else {
$this->doBrowse();
}
break;
case 'confdelrow':
$this->doDelRow(true);
break;
default:
$header_template = 'header_sqledit.twig';
$footer_template = 'footer_sqledit.twig';
$this->doBrowse();
break;
}
$output = ob_get_clean();
$subject = $this->coalesceArr($_REQUEST, 'subject', 'table')['subject'];
$object = null;
$object = $this->setIfIsset($object, $_REQUEST[$subject]);
// Set the title based on the subject of the request
if ('table' == $subject) {
$title = $this->headerTitle('strtables', '', $object);
} elseif ('view' == $subject) {
$title = $this->headerTitle('strviews', '', $object);
} elseif ('matview' == $subject) {
$title = $this->headerTitle('strviews', 'M', $object);
} elseif ('column' == $subject) {
$title = $this->headerTitle('strcolumn', '', $object);
} else {
$title = $this->headerTitle('strqueryresults');
}
$this->printHeader($title, $scripts, true, $header_template);
$this->printBody();
echo $output;
$this->printFooter(true, $footer_template);
}
/**
* Displays requested data.
*
* @param mixed $msg
*/
public function doBrowse($msg = '')
{
$this->misc = $this->misc;
$data = $this->misc->getDatabaseAccessor();
// If current page is not set, default to first page
$page = $this->coalesceArr($_REQUEST, 'page', 1)['page'];
$save_history = !isset($_REQUEST['nohistory']);
$subject = $this->coalesceArr($_REQUEST, 'subject', 'table')['subject'];
$object = $this->coalesceArr($_REQUEST, $subject)[$subject];
if ($subject === 'column' && $object && isset($_REQUEST['f_schema'], $_REQUEST['f_table'])) {
$f_schema = $_REQUEST['f_schema'];
$f_table = $_REQUEST['f_table'];
$_REQUEST['query'] = "SELECT \"{$object}\",
count(*) AS \"count\"
FROM \"{$f_schema}\".\"{$f_table}\"
GROUP BY \"{$object}\" ORDER BY \"{$object}\"";
} elseif ($subject === 'table' && !isset($_REQUEST['query'])) {
$show = $this->getPostParam('show', []);
$values = $this->getPostParam('values', []);
$ops = $this->getPostParam('ops', []);
$query = $data->getSelectSQL(
$_REQUEST['table'],
array_keys($show),
$values,
$ops
);
$_REQUEST['query'] = $query;
$_REQUEST['return'] = 'selectrows';
}
//$object = $this->setIfIsset($object, $_REQUEST[$subject]);
$this->printTrail($subject);
$tabsPosition = 'browse';
if ($subject === 'database') {
$tabsPosition = 'sql';
} elseif ($subject === 'column') {
$tabsPosition = 'colproperties';
}
$this->printTabs($subject, $tabsPosition);
list($query, $title, $type) = $this->getQueryTitleAndType($data, $object);
$this->printTitle($this->lang[$title]);
//$this->prtrace($subject, $object, $query, $_SESSION['sqlquery']);
$this->printMsg($msg);
// If 'sortkey' is not set, default to ''
$sortkey = $this->coalesceArr($_REQUEST, 'sortkey', '')['sortkey'];
// If 'sortdir' is not set, default to ''
$sortdir = $this->coalesceArr($_REQUEST, 'sortdir', '')['sortdir'];
// If 'strings' is not set, default to collapsed
$strings = $this->coalesceArr($_REQUEST, 'strings', 'collapsed')['strings'];
$this->coalesceArr($_REQUEST, 'schema')['schema'];
$search_path = $this->coalesceArr($_REQUEST, 'search_path')['search_path'];
// Set the schema search path
if (isset($search_path) && (0 != $data->setSearchPath(array_map('trim', explode(',', $search_path))))) {
return;
}
try {
// Retrieve page from query. $max_pages is returned by reference.
$resultset = $data->browseQuery(
$type,
$object,
$query,
$sortkey,
$sortdir,
$page,
$this->conf['max_rows'],
$max_pages
);
} catch (\PHPPgAdmin\ADOdbException $e) {
return $this->halt($e->getMessage());
}
// Build strings for GETs in array
$_gets = [
'server' => $_REQUEST['server'],
'database' => $_REQUEST['database'],
];
$this->coalesceArr($_REQUEST, 'query');
$this->coalesceArr($_REQUEST, 'count');
$this->coalesceArr($_REQUEST, 'return');
$this->coalesceArr($_REQUEST, 'table');
$this->coalesceArr($_REQUEST, 'nohistory');
$this->setIfIsset($_gets['schema'], $_REQUEST['schema'], null, false);
$this->setIfIsset($_gets[$subject], $object, null, false);
$this->setIfIsset($_gets['subject'], $subject, null, false);
$this->setIfIsset($_gets['query'], $_REQUEST['query'], null, false);
$this->setIfIsset($_gets['count'], $_REQUEST['count'], null, false);
$this->setIfIsset($_gets['return'], $_REQUEST['return'], null, false);
$this->setIfIsset($_gets['search_path'], $_REQUEST['search_path'], null, false);
$this->setIfIsset($_gets['table'], $_REQUEST['table'], null, false);
$this->setIfIsset($_gets['nohistory'], $_REQUEST['nohistory'], null, false);
$_gets['sortkey'] = $sortkey;
$_gets['sortdir'] = $sortdir;
$_gets['strings'] = $strings;
if ($save_history && is_object($resultset) && ('QUERY' == $type)) {
//{
$this->misc->saveScriptHistory($_REQUEST['query']);
}
$query = $query ? $query : sprintf('SELECT * FROM %s.%s', $_REQUEST['schema'], $object);
//$query = isset($_REQUEST['query'])? $_REQUEST['query'] : "select * from {$_REQUEST['schema']}.{$_REQUEST['table']};";
//$this->prtrace($query);
//die(htmlspecialchars($query));
echo '
';
$this->printResultsTable($resultset, $page, $max_pages, $_gets, $object);
// Navigation links
$navlinks = $this->getBrowseNavLinks($type, $_gets, $page, $subject, $object, $resultset);
$this->printNavLinks($navlinks, 'display-browse', get_defined_vars());
}
public function getQueryTitleAndType($data, $object)
{
$fkey = $this->coalesceArr($_REQUEST, 'fkey')['fkey'];
$query = $this->coalesceArr($_REQUEST, 'query')['query'];
// This code is used when browsing FK in pure-xHTML (without js)
if ($fkey) {
$ops = [];
foreach (array_keys($fkey) as $x) {
$ops[$x] = '=';
}
$query = $data->getSelectSQL($_REQUEST['table'], [], $fkey, $ops);
$_REQUEST['query'] = $query;
}
$title = 'strqueryresults';
$type = 'QUERY';
if ($object && $query) {
$_SESSION['sqlquery'] = $query;
$title = 'strselect';
$type = 'SELECT';
} elseif ($object) {
$title = 'strselect';
$type = 'TABLE';
} elseif (isset($_SESSION['sqlquery'])) {
$query = $_SESSION['sqlquery'];
}
return [$query, $title, $type];
}
public function getBrowseNavLinks($type, $_gets, $page, $subject, $object, $resultset)
{
$fields = [
'server' => $_REQUEST['server'],
'database' => $_REQUEST['database'],
];
$this->setIfIsset($fields['schema'], $_REQUEST['schema'], null, false);
$navlinks = [];
$strings = $_gets['strings'];
// Return
if (isset($_REQUEST['return'])) {
$urlvars = $this->misc->getSubjectParams($_REQUEST['return']);
$navlinks['back'] = [
'attr' => [
'href' => [
'url' => $urlvars['url'],
'urlvars' => $urlvars['params'],
],
],
'content' => $this->lang['strback'],
];
}
// Edit SQL link
if ('QUERY' == $type) {
$navlinks['edit'] = [
'attr' => [
'href' => [
'url' => 'database',
'urlvars' => array_merge(
$fields,
[
'action' => 'sql',
'paginate' => 'on',
]
),
],
],
'content' => $this->lang['streditsql'],
];
}
$navlinks['collapse'] = [
'attr' => [
'href' => [
'url' => 'display',
'urlvars' => array_merge(
$_gets,
[
'strings' => 'expanded',
'page' => $page,
]
),
],
],
'content' => $this->lang['strexpand'],
];
// Expand/Collapse
if ('expanded' == $strings) {
$navlinks['collapse'] = [
'attr' => [
'href' => [
'url' => 'display',
'urlvars' => array_merge(
$_gets,
[
'strings' => 'collapsed',
'page' => $page,
]
),
],
],
'content' => $this->lang['strcollapse'],
];
}
// Create view and download
if (isset($_REQUEST['query'], $resultset) && is_object($resultset) && $resultset->recordCount() > 0) {
// Report views don't set a schema, so we need to disable create view in that case
if (isset($_REQUEST['schema'])) {
$navlinks['createview'] = [
'attr' => [
'href' => [
'url' => 'views',
'urlvars' => array_merge(
$fields,
[
'action' => 'create',
'formDefinition' => $_REQUEST['query'],
]
),
],
],
'content' => $this->lang['strcreateview'],
];
}
$urlvars = [];
$this->setIfIsset($urlvars['search_path'], $_REQUEST['search_path'], null, false);
$navlinks['download'] = [
'attr' => [
'href' => [
'url' => 'dataexport',
'urlvars' => array_merge($fields, $urlvars),
],
],
'content' => $this->lang['strdownload'],
];
}
// Insert
if (isset($object) && (isset($subject) && 'table' == $subject)) {
$navlinks['insert'] = [
'attr' => [
'href' => [
'url' => 'tables',
'urlvars' => array_merge(
$fields,
[
'action' => 'confinsertrow',
'table' => $object,
]
),
],
],
'content' => $this->lang['strinsert'],
];
}
// Refresh
$navlinks['refresh'] = [
'attr' => [
'href' => [
'url' => 'display',
'urlvars' => array_merge(
$_gets,
[
'strings' => $strings,
'page' => $page,
]
),
],
],
'content' => $this->lang['strrefresh'],
];
return $navlinks;
}
private function _getKeyAndActions($resultset, $object, $data, $page, $_gets)
{
$key = [];
$strings = $_gets['strings'];
$plugin_manager = $this->plugin_manager;
// Fetch unique row identifier, if this is a table browse request.
if ($object) {
$key = $data->getRowIdentifier($object);
}
// Check that the key is actually in the result set. This can occur for select
// operations where the key fields aren't part of the select. XXX: We should
// be able to support this, somehow.
foreach ($key as $v) {
// If a key column is not found in the record set, then we
// can't use the key.
if (!array_key_exists($v, $resultset->fields)) {
$key = [];
break;
}
}
$buttons = [
'edit' => [
'content' => $this->lang['stredit'],
'attr' => [
'href' => [
'url' => 'display',
'urlvars' => array_merge(
[
'action' => 'confeditrow',
'strings' => $strings,
'page' => $page,
],
$_gets
),
],
],
],
'delete' => [
'content' => $this->lang['strdelete'],
'attr' => [
'href' => [
'url' => 'display',
'urlvars' => array_merge(
[
'action' => 'confdelrow',
'strings' => $strings,
'page' => $page,
],
$_gets
),
],
],
],
];
$actions = [
'actionbuttons' => &$buttons,
'place' => 'display-browse',
];
$plugin_manager->doHook('actionbuttons', $actions);
foreach (array_keys($actions['actionbuttons']) as $action) {
$actions['actionbuttons'][$action]['attr']['href']['urlvars'] = array_merge(
$actions['actionbuttons'][$action]['attr']['href']['urlvars'],
$_gets
);
}
return [$actions, $key];
}
public function printResultsTable($resultset, $page, $max_pages, $_gets, $object)
{
if (!is_object($resultset) || $resultset->recordCount() <= 0) {
echo "{$this->lang['strnodata']}
".PHP_EOL;
return;
}
$data = $this->misc->getDatabaseAccessor();
list($actions, $key) = $this->_getKeyAndActions($resultset, $object, $data, $page, $_gets);
$fkey_information = $this->getFKInfo();
// Show page navigation
$paginator = $this->_printPages($page, $max_pages, $_gets);
echo $paginator;
echo ''.PHP_EOL;
echo '';
// Display edit and delete actions if we have a key
$display_action_column = (count($actions['actionbuttons']) > 0 && count($key) > 0);
echo $display_action_column ? "{$this->lang['stractions']} ".PHP_EOL : '';
// we show OIDs only if we are in TABLE or SELECT type browsing
$this->printTableHeaderCells($resultset, $_gets, isset($object));
echo ' '.PHP_EOL;
reset($resultset->fields);
$trclass = 'data2';
$buttonclass = 'opbutton2';
while (!$resultset->EOF) {
$trclass = ($trclass === 'data2') ? 'data1' : 'data2';
$buttonclass = ($buttonclass === 'opbutton2') ? 'opbutton1' : 'opbutton2';
echo sprintf('', $trclass).PHP_EOL;
$this->_printResultsTableActionButtons($resultset, $key, $actions, $display_action_column, $buttonclass);
$this->printTableRowCells($resultset, $fkey_information, isset($object));
echo ' '.PHP_EOL;
$resultset->moveNext();
}
echo '
'.PHP_EOL;
echo '', $resultset->recordCount(), " {$this->lang['strrows']}
".PHP_EOL;
// Show page navigation
echo $paginator;
}
private function _printResultsTableActionButtons($resultset, $key, $actions, $display_action_column, $buttonclass)
{
if (!$display_action_column) {
return;
}
$edit_params = isset($actions['actionbuttons']['edit']) ? $actions['actionbuttons']['edit'] : [];
$delete_params = isset($actions['actionbuttons']['delete']) ? $actions['actionbuttons']['delete'] : [];
$keys_array = [];
$has_nulls = false;
foreach ($key as $v) {
if (null === $resultset->fields[$v]) {
$has_nulls = true;
break;
}
$keys_array["key[{$v}]"] = $resultset->fields[$v];
}
if ($has_nulls) {
echo ' '.PHP_EOL;
return;
}
// Display edit and delete links if we have a key
if (isset($actions['actionbuttons']['edit'])) {
$actions['actionbuttons']['edit'] = $edit_params;
$actions['actionbuttons']['edit']['attr']['href']['urlvars'] = array_merge(
$actions['actionbuttons']['edit']['attr']['href']['urlvars'],
$keys_array
);
}
if (isset($actions['actionbuttons']['delete'])) {
$actions['actionbuttons']['delete'] = $delete_params;
$actions['actionbuttons']['delete']['attr']['href']['urlvars'] = array_merge(
$actions['actionbuttons']['delete']['attr']['href']['urlvars'],
$keys_array
);
}
echo sprintf('', $buttonclass);
foreach ($actions['actionbuttons'] as $action) {
$this->printLink($action, true, __METHOD__);
}
echo ' '.PHP_EOL;
}
/**
* Print table header cells.
*
* @param \PHPPgAdmin\ADORecordSet $resultset set of results from getRow operation
* @param array|bool $args - associative array for sort link parameters, or false if there isn't any
* @param bool $withOid either to display OIDs or not
*/
public function printTableHeaderCells(&$resultset, $args, $withOid)
{
$data = $this->misc->getDatabaseAccessor();
if (!is_object($resultset) || $resultset->recordCount() <= 0) {
return;
}
foreach (array_keys($resultset->fields) as $index => $key) {
if (($key === $data->id) && (!($withOid && $this->conf['show_oids']))) {
continue;
}
$finfo = $resultset->fetchField($index);
if (false === $args) {
echo '', $this->misc->printVal($finfo->name), ' '.PHP_EOL;
continue;
}
$args['page'] = $_REQUEST['page'];
$args['sortkey'] = $index + 1;
// Sort direction opposite to current direction, unless it's currently ''
$args['sortdir'] = ('asc' == $_REQUEST['sortdir'] && $_REQUEST['sortkey'] == ($index + 1)) ? 'desc' : 'asc';
$sortLink = http_build_query($args);
echo "";
echo $this->misc->printVal($finfo->name);
if ($_REQUEST['sortkey'] == ($index + 1)) {
$icon = ('asc' == $_REQUEST['sortdir']) ? $this->misc->icon('RaiseArgument') : $this->misc->icon('LowerArgument');
echo sprintf(' ', $icon, $_REQUEST['sortdir']);
}
echo ' '.PHP_EOL;
}
reset($resultset->fields);
}
/**
* Print table rows.
*
* @param \PHPPgAdmin\ADORecordSet $resultset The resultset
* @param array $fkey_information The fkey information
* @param bool $withOid either to display OIDs or not
*/
public function printTableRowCells(&$resultset, &$fkey_information, $withOid)
{
$data = $this->misc->getDatabaseAccessor();
$j = 0;
$this->coalesceArr($_REQUEST, 'strings', 'collapsed');
foreach ($resultset->fields as $k => $v) {
$finfo = $resultset->fetchField($j++);
if (($k === $data->id) && (!($withOid && $this->conf['show_oids']))) {
continue;
}
$printvalOpts = ['null' => true, 'clip' => ('collapsed' == $_REQUEST['strings'])];
if (null !== $v && '' == $v) {
echo ' ';
} else {
echo '';
$this->_printFKLinks($resultset, $fkey_information, $k, $v, $printvalOpts);
$val = $this->misc->printVal($v, $finfo->type, $printvalOpts);
echo $val;
echo ' ';
}
}
}
private function _printFKLinks($resultset, $fkey_information, $k, $v, &$printvalOpts)
{
if ((null === $v) || !isset($fkey_information['byfield'][$k])) {
return;
}
foreach ($fkey_information['byfield'][$k] as $conid) {
$query_params = $fkey_information['byconstr'][$conid]['url_data'];
foreach ($fkey_information['byconstr'][$conid]['fkeys'] as $p_field => $f_field) {
$query_params .= '&'.urlencode("fkey[{$f_field}]").'='.urlencode($resultset->fields[$p_field]);
}
// $fkey_information['common_url'] is already urlencoded
$query_params .= '&'.$fkey_information['common_url'];
$title = htmlentities($fkey_information['byconstr'][$conid]['consrc'], ENT_QUOTES, 'UTF-8');
echo '';
}
$printvalOpts['class'] = 'fk_value';
}
private function _unserializeIfNotArray($the_array, $key)
{
if (!isset($the_array[$key])) {
return [];
}
if (is_array($the_array[$key])) {
return $the_array[$key];
}
return unserialize(urldecode($the_array[$key]));
}
/**
* Show form to edit row.
*
* @param string $msg message to display on top of the form or after performing edition
*/
public function formEditRow($msg = '')
{
$data = $this->misc->getDatabaseAccessor();
$key = $this->_unserializeIfNotArray($_REQUEST, 'key');
$this->printTrail($_REQUEST['subject']);
$this->printTitle($this->lang['streditrow']);
$this->printMsg($msg);
$attrs = $data->getTableAttributes($_REQUEST['table']);
$resultset = $data->browseRow($_REQUEST['table'], $key);
$fksprops = $this->_getFKProps();
echo ''.PHP_EOL;
$elements = 0;
$error = true;
if (1 == $resultset->recordCount() && $attrs->recordCount() > 0) {
echo ''.PHP_EOL;
// Output table header
echo "{$this->lang['strcolumn']} {$this->lang['strtype']} ";
echo "{$this->lang['strformat']} ".PHP_EOL;
echo "{$this->lang['strnull']} {$this->lang['strvalue']} ";
$i = 0;
while (!$attrs->EOF) {
$attrs->fields['attnotnull'] = $data->phpBool($attrs->fields['attnotnull']);
$id = (0 == ($i % 2) ? '1' : '2');
// Initialise variables
if (!isset($_REQUEST['format'][$attrs->fields['attname']])) {
$_REQUEST['format'][$attrs->fields['attname']] = 'VALUE';
}
echo "".PHP_EOL;
echo '', $this->misc->printVal($attrs->fields['attname']), ' ';
echo ''.PHP_EOL;
echo $this->misc->printVal($data->formatType($attrs->fields['type'], $attrs->fields['atttypmod']));
echo ' ';
++$elements;
echo ''.PHP_EOL;
echo ''.PHP_EOL;
echo 'fields['attname']] == 'VALUE') ? ' selected="selected"' : '', ">{$this->lang['strvalue']} ".PHP_EOL;
$selected = ($_REQUEST['format'][$attrs->fields['attname']] == 'EXPRESSION') ? ' selected="selected"' : '';
echo '{$this->lang['strexpression']} ".PHP_EOL;
echo " \n ".PHP_EOL;
++$elements;
echo '';
// Output null box if the column allows nulls (doesn't look at CHECKs or ASSERTIONS)
if (!$attrs->fields['attnotnull']) {
// Set initial null values
if (
'confeditrow' == $_REQUEST['action']
&& null === $resultset->fields[$attrs->fields['attname']]
) {
$_REQUEST['nulls'][$attrs->fields['attname']] = 'on';
}
echo " fields['attname']}]\"",
isset($_REQUEST['nulls'][$attrs->fields['attname']]) ? ' checked="checked"' : '', ' /> '.PHP_EOL;
++$elements;
} else {
echo ' ';
}
echo "fields['attnum']}\" style=\"white-space:nowrap;\">";
$extras = [];
// If the column allows nulls, then we put a JavaScript action on the data field to unset the
// NULL checkbox as soon as anything is entered in the field. We use the $elements variable to
// keep track of which element offset we're up to. We can't refer to the null checkbox by name
// as it contains '[' and ']' characters.
if (!$attrs->fields['attnotnull']) {
$extras['class'] = 'insert_row_input';
}
if ((false !== $fksprops) && isset($fksprops['byfield'][$attrs->fields['attnum']])) {
$extras['id'] = "attr_{$attrs->fields['attnum']}";
$extras['autocomplete'] = 'off';
}
echo $data->printField("values[{$attrs->fields['attname']}]", $resultset->fields[$attrs->fields['attname']], $attrs->fields['type'], $extras);
echo ' ';
++$elements;
echo ' '.PHP_EOL;
++$i;
$attrs->moveNext();
}
echo '
'.PHP_EOL;
$error = false;
} elseif (1 != $resultset->recordCount()) {
echo "{$this->lang['strrownotunique']}
".PHP_EOL;
} else {
echo "{$this->lang['strinvalidparam']}
".PHP_EOL;
}
echo ' '.PHP_EOL;
echo $this->misc->form;
echo isset($_REQUEST['table']) ? sprintf(' %s', htmlspecialchars($_REQUEST['table']), PHP_EOL) : '';
echo isset($_REQUEST['subject']) ? sprintf(' %s', htmlspecialchars($_REQUEST['subject']), PHP_EOL) : '';
echo isset($_REQUEST['query']) ? sprintf(' %s', htmlspecialchars($_REQUEST['query']), PHP_EOL) : '';
echo isset($_REQUEST['count']) ? sprintf(' %s', htmlspecialchars($_REQUEST['count']), PHP_EOL) : '';
echo isset($_REQUEST['return']) ? sprintf(' %s', htmlspecialchars($_REQUEST['return']), PHP_EOL) : '';
echo ' '.PHP_EOL;
echo ' '.PHP_EOL;
echo ' '.PHP_EOL;
echo ' '.PHP_EOL;
echo ' '.PHP_EOL;
echo '';
if (!$error) {
echo " lang['strsave']}\" />".PHP_EOL;
}
echo " lang['strcancel']}\" />".PHP_EOL;
if (false !== $fksprops) {
$autocomplete_string = "{$this->lang['strac']} ";
if ('default off' != $this->conf['autocomplete']) {
$autocomplete_string = "{$this->lang['strac']} ";
}
echo $autocomplete_string.PHP_EOL;
}
echo '
'.PHP_EOL;
echo ' '.PHP_EOL;
echo '';
}
/**
* Performs actual edition of row.
*/
public function doEditRow()
{
$data = $this->misc->getDatabaseAccessor();
$key = $this->_unserializeIfNotArray($_REQUEST, 'key');
$this->coalesceArr($_POST, 'values', []);
$this->coalesceArr($_POST, 'nulls', []);
$status = $data->editRow(
$_POST['table'],
$_POST['values'],
$_POST['nulls'],
$_POST['format'],
$_POST['types'],
$key
);
if (0 == $status) {
return $this->doBrowse($this->lang['strrowupdated']);
}
if ($status == -2) {
return $this->formEditRow($this->lang['strrownotunique']);
}
return $this->formEditRow($this->lang['strrowupdatedbad']);
}
/**
* Show confirmation of drop and perform actual drop.
*
* @param mixed $confirm
*/
public function doDelRow($confirm)
{
$data = $this->misc->getDatabaseAccessor();
if ($confirm) {
$this->printTrail($_REQUEST['subject']);
$this->printTitle($this->lang['strdeleterow']);
$resultset = $data->browseRow($_REQUEST['table'], $_REQUEST['key']);
echo ''.PHP_EOL;
echo $this->misc->form;
if (1 == $resultset->recordCount()) {
echo "{$this->lang['strconfdeleterow']}
".PHP_EOL;
$fkinfo = [];
echo '';
$this->printTableHeaderCells($resultset, false, true);
echo ' ';
echo ''.PHP_EOL;
$this->printTableRowCells($resultset, $fkinfo, true);
echo ' '.PHP_EOL;
echo '
'.PHP_EOL;
echo ' '.PHP_EOL;
echo ' '.PHP_EOL;
echo " lang['stryes']}\" />".PHP_EOL;
echo " lang['strno']}\" />".PHP_EOL;
} elseif (1 != $resultset->recordCount()) {
echo "{$this->lang['strrownotunique']}
".PHP_EOL;
echo " lang['strcancel']}\" />".PHP_EOL;
} else {
echo "{$this->lang['strinvalidparam']}
".PHP_EOL;
echo " lang['strcancel']}\" />".PHP_EOL;
}
if (isset($_REQUEST['table'])) {
echo ' '.PHP_EOL;
}
if (isset($_REQUEST['subject'])) {
echo ' '.PHP_EOL;
}
if (isset($_REQUEST['query'])) {
echo ' '.PHP_EOL;
}
if (isset($_REQUEST['count'])) {
echo ' '.PHP_EOL;
}
if (isset($_REQUEST['return'])) {
echo ' '.PHP_EOL;
}
echo ' '.PHP_EOL;
echo ' '.PHP_EOL;
echo ' '.PHP_EOL;
echo ' '.PHP_EOL;
echo ' '.PHP_EOL;
echo ' '.PHP_EOL;
} else {
$status = $data->deleteRow($_POST['table'], unserialize(urldecode($_POST['key'])));
if (0 == $status) {
$this->doBrowse($this->lang['strrowdeleted']);
} elseif ($status == -2) {
$this->doBrowse($this->lang['strrownotunique']);
} else {
$this->doBrowse($this->lang['strrowdeletedbad']);
}
}
}
/**
* Build & return the FK information data structure
* used when deciding if a field should have a FK link or not.
*
* @return array associative array describing the FK
*/
public function &getFKInfo()
{
$data = $this->misc->getDatabaseAccessor();
// Get the foreign key(s) information from the current table
$fkey_information = ['byconstr' => [], 'byfield' => []];
if (isset($_REQUEST['table'])) {
$constraints = $data->getConstraintsWithFields($_REQUEST['table']);
if ($constraints->recordCount() > 0) {
$fkey_information['common_url'] = $this->misc->getHREF('schema').'&subject=table';
// build the FK constraints data structure
while (!$constraints->EOF) {
$constr = &$constraints->fields;
if ('f' == $constr['contype']) {
if (!isset($fkey_information['byconstr'][$constr['conid']])) {
$fkey_information['byconstr'][$constr['conid']] = [
'url_data' => 'table='.urlencode($constr['f_table']).'&schema='.urlencode($constr['f_schema']),
'fkeys' => [],
'consrc' => $constr['consrc'],
];
}
$fkey_information['byconstr'][$constr['conid']]['fkeys'][$constr['p_field']] = $constr['f_field'];
if (!isset($fkey_information['byfield'][$constr['p_field']])) {
$fkey_information['byfield'][$constr['p_field']] = [];
}
$fkey_information['byfield'][$constr['p_field']][] = $constr['conid'];
}
$constraints->moveNext();
}
}
}
return $fkey_information;
}
// Print the FK row, used in ajax requests
public function doBrowseFK()
{
$data = $this->misc->getDatabaseAccessor();
$ops = [];
foreach ($_REQUEST['fkey'] as $x => $y) {
$ops[$x] = '=';
}
$query = $data->getSelectSQL($_REQUEST['table'], [], $_REQUEST['fkey'], $ops);
$_REQUEST['query'] = $query;
$fkinfo = $this->getFKInfo();
$max_pages = 1;
// Retrieve page from query. $max_pages is returned by reference.
$resultset = $data->browseQuery(
'SELECT',
$_REQUEST['table'],
$_REQUEST['query'],
null,
null,
1,
1,
$max_pages
);
echo ' '.PHP_EOL;
echo '';
if (is_object($resultset) && $resultset->recordCount() > 0) {
/* we are browsing a referenced table here
* we should show OID if show_oids is true
* so we give true to withOid in functions bellow
*/
echo '
';
$this->printTableHeaderCells($resultset, false, true);
echo ' ';
echo ''.PHP_EOL;
$this->printTableRowCells($resultset, $fkinfo, true);
echo ' '.PHP_EOL;
echo '
'.PHP_EOL;
} else {
echo $this->lang['strnodata'];
}
echo '
';
}
private function _getMinMaxPages($page, $pages)
{
$window = 10;
if ($page <= $window) {
$min_page = 1;
$max_page = min(2 * $window, $pages);
} elseif ($page > $window && $pages >= $page + $window) {
$min_page = ($page - $window) + 1;
$max_page = $page + $window;
} else {
$min_page = ($page - (2 * $window - ($pages - $page))) + 1;
$max_page = $pages;
}
// Make sure min_page is always at least 1
// and max_page is never greater than $pages
$min_page = max($min_page, 1);
$max_page = min($max_page, $pages);
return [$min_page, $max_page];
}
/**
* Do multi-page navigation. Displays the prev, next and page options.
*
* @param int $page - the page currently viewed
* @param int $pages - the maximum number of pages
* @param array $gets - the parameters to include in the link to the wanted page
* @param int $max_width - the number of pages to make available at any one time (default = 20)
*
* @return string the pagination links
*/
private function _printPages($page, $pages, $gets, $max_width = 20)
{
$lang = $this->lang;
$page = (int) $page;
if ($page < 0 || $page > $pages || $pages <= 1 || $max_width <= 0) {
return;
}
unset($gets['page']);
$url = http_build_query($gets);
$result = ''.PHP_EOL;
if ($page != 1) {
$result .= sprintf('%s %s ', $url, $lang['strfirst'], PHP_EOL);
$result .= sprintf('%s %s', $url, $page - 1, $lang['strprev'], PHP_EOL);
}
list($min_page, $max_page) = $this->_getMinMaxPages($page, $pages);
for ($i = $min_page; $i <= $max_page; ++$i) {
$result .= (($i === $page) ? $i : sprintf('%s ', $url, $i, $i)).PHP_EOL;
}
if ($page != $pages) {
$result .= sprintf('%s %s', $url, $page + 1, $lang['strnext'], PHP_EOL);
$result .= sprintf(' %s %s', $url, $pages, $lang['strlast'], PHP_EOL);
}
$result .= '
'.PHP_EOL;
return $result;
}
}