Fix auto-complete when editing a row.
authorGuillaume (ioguix) de Rorthais <ioguix@free.fr>
Wed, 22 Sep 2010 22:28:54 +0000 (00:28 +0200)
committerGuillaume (ioguix) de Rorthais <ioguix@free.fr>
Thu, 23 Sep 2010 00:14:02 +0000 (02:14 +0200)
Reported by Dmitry Koterov when asked on github:
http://github.com/DmitryKoterov/phppgadmin/commit/89460c1557816b40311e8a344bf94c8a0f505542#commitcomment-148877

classes/Misc.php
classes/database/Postgres.php
display.php
tables.php

index 2dc28b2a309a26b675d0d7eae2b3875a9034bf0f..b92e1dbf1213de3c9e981fbd4c8d2b16167fafc1 100644 (file)
                        
                        echo "</td></tr></table>\n";
                }
+
+               function getAutocompleteFKProperties($table) {
+                       global $data;
+
+                       $fksprops = array(
+                               'byconstr' => array(),
+                               'byfield' => array(),
+                               'code' => ''
+                       );
+
+                       $constrs = $data->getConstraintsWithFields($table);
+
+                       if (!$constrs->EOF) {
+                               $conrelid = $constrs->fields['conrelid'];
+                               while(!$constrs->EOF) {
+                                       if ($constrs->fields['contype'] == 'f') {
+                                               if (!isset($fksprops['byconstr'][$constrs->fields['conid']])) {
+                                                       $fksprops['byconstr'][$constrs->fields['conid']] = array (
+                                                               'confrelid' => $constrs->fields['confrelid'],
+                                                               'f_table' => $constrs->fields['f_table'],
+                                                               'f_schema' => $constrs->fields['f_schema'],
+                                                               'pattnums' => array(),
+                                                               'pattnames' => array(),
+                                                               'fattnames' => array()
+                                                       );
+                                               }
+
+                                               $fksprops['byconstr'][$constrs->fields['conid']]['pattnums'][] = $constrs->fields['p_attnum'];
+                                               $fksprops['byconstr'][$constrs->fields['conid']]['pattnames'][] = $constrs->fields['p_field'];
+                                               $fksprops['byconstr'][$constrs->fields['conid']]['fattnames'][] = $constrs->fields['f_field'];
+
+                                               if (!isset($fksprops['byfield'][$constrs->fields['p_attnum']]))
+                                                       $fksprops['byfield'][$constrs->fields['p_attnum']] = array();
+                                               $fksprops['byfield'][$constrs->fields['p_attnum']] = $constrs->fields['conid'];
+                                       }
+                                       $constrs->moveNext();
+                               }
+
+                               $fksprops['code'] = "<script type=\"text/javascript\">\n";
+                               $fksprops['code'] .= "var constrs = {};\n";
+                               foreach ($fksprops['byconstr'] as $conid => $props) {
+                                       $fksprops['code'] .= "constrs.constr_{$conid} = {\n";
+                                       $fksprops['code'] .= 'pattnums: ['. implode(',',$props['pattnums']) ."],\n";
+                                       $fksprops['code'] .= "f_table:\"". htmlentities($props['f_table']) ."\",\n";
+                                       $fksprops['code'] .= "f_schema:\"". htmlentities($props['f_schema']) ."\",\n";
+                                       $_ = '';
+                                       foreach ($props['pattnames'] as $n) {
+                                               $_ .= ",'". htmlentities($n, ENT_QUOTES) ."'";
+                                       }
+                                       $fksprops['code'] .= 'pattnames: ['. substr($_, 1) ."],\n";
+
+                                       $_ = '';
+                                       foreach ($props['fattnames'] as $n) {
+                                               $_ .= ",'". htmlentities($n, ENT_QUOTES) ."'";
+                                       }
+
+                                       $fksprops['code'] .= 'fattnames: ['. substr($_, 1) ."]\n";
+                                       $fksprops['code'] .= "};\n";
+                               }
+
+                               $fksprops['code'] .= "var attrs = {};\n";
+                               foreach ($fksprops['byfield'] as $attnum => $cstrs ) {
+                                       $fksprops['code'] .= "attrs.attr_{$attnum} = {$fksprops['byfield'][$attnum]};\n";
+                               }
+
+                               $fksprops['code'] .= "var table='". htmlentities($_REQUEST['table']) ."';";
+                               $fksprops['code'] .= "var server='". htmlentities($_REQUEST['server']) ."';";
+                               $fksprops['code'] .= "var database='". htmlentities($_REQUEST['database']) ."';";
+                               $fksprops['code'] .= "</script>\n";
+
+                               $fksprops['code'] .= '<div id="fkbg"></div>';
+                               $fksprops['code'] .= '<div id="fklist"></div>';
+                               $fksprops['code'] .= '<script src="libraries/js/jquery.js" type="text/javascript"></script>';
+                               $fksprops['code'] .= '<script src="js/ac_insert_row.js" type="text/javascript"></script>';
+                       }
+
+                       else /* we have no foreign keys on this table */
+                               return false;
+
+                       return $fksprops;
+               }
        }
 ?>
index a0c566f13737899d53c638b33a343880827fc6d1..0178e327dcb6aa695bc25d9f3852195331eeb54c 100755 (executable)
@@ -249,16 +249,15 @@ class Postgres extends ADODB_base {
         * @param $name The name to give the field
         * @param $value The value of the field.  Note this could be 'numeric(7,2)' sort of thing...
         * @param $type The database type of the field
-        * @param $actions An array of javascript action name to the code to execute on that action
-        * @param $extra Some extra attributes to add.
+        * @param $extras An array of attributes name as key and attributes' values as value
         */
-       function printField($name, $value, $type, $actions = array(), $extra='') {
+       function printField($name, $value, $type, $extras = array()) {
                global $lang;
 
                // Determine actions string
-               $action_str = '';
-               foreach ($actions as $k => $v) {
-                       $action_str .= " {$k}=\"" . htmlspecialchars($v) . "\"";
+               $extra_str = '';
+               foreach ($extras as $k => $v) {
+                       $extra_str .= " {$k}=\"" . htmlspecialchars($v) . "\"";
                }
 
                switch (substr($type,0,9)) {
@@ -270,14 +269,14 @@ class Postgres extends ADODB_base {
 
                                // If value is null, 't' or 'f'...
                                if ($value === null || $value == 't' || $value == 'f') {
-                                       echo "<select name=\"", htmlspecialchars($name), "\"{$action_str}>\n";
+                                       echo "<select name=\"", htmlspecialchars($name), "\"{$extra_str}>\n";
                                        echo "<option value=\"\"", ($value === null) ? ' selected="selected"' : '', "></option>\n";
                                        echo "<option value=\"t\"", ($value == 't') ? ' selected="selected"' : '', ">{$lang['strtrue']}</option>\n";
                                        echo "<option value=\"f\"", ($value == 'f') ? ' selected="selected"' : '', ">{$lang['strfalse']}</option>\n";
                                        echo "</select>\n";
                                }
                                else {
-                                       echo "<input name=\"", htmlspecialchars($name), "\" value=\"", htmlspecialchars($value), "\" size=\"35\"{$action_str} {$extra} />\n";
+                                       echo "<input name=\"", htmlspecialchars($name), "\" value=\"", htmlspecialchars($value), "\" size=\"35\"{$extra_str} />\n";
                                }
                                break;
                        case 'bytea':
@@ -290,7 +289,7 @@ class Postgres extends ADODB_base {
                                $n = substr_count($value, "\n");
                                $n = $n < 5 ? 5 : $n;
                                $n = $n > 20 ? 20 : $n;
-                               echo "<textarea name=\"", htmlspecialchars($name), "\" rows=\"{$n}\" cols=\"75\"{$action_str}>\n";
+                               echo "<textarea name=\"", htmlspecialchars($name), "\" rows=\"{$n}\" cols=\"75\"{$extra_str}>\n";
                                echo htmlspecialchars($value);
                                echo "</textarea>\n";
                                break;
@@ -299,12 +298,12 @@ class Postgres extends ADODB_base {
                                $n = substr_count($value, "\n");
                                $n = $n < 5 ? 5 : $n;
                                $n = $n > 20 ? 20 : $n;
-                               echo "<textarea name=\"", htmlspecialchars($name), "\" rows=\"{$n}\" cols=\"35\"{$action_str}>\n";
+                               echo "<textarea name=\"", htmlspecialchars($name), "\" rows=\"{$n}\" cols=\"35\"{$extra_str}>\n";
                                echo htmlspecialchars($value);
                                echo "</textarea>\n";
                                break;
                        default:
-                               echo "<input name=\"", htmlspecialchars($name), "\" value=\"", htmlspecialchars($value), "\" size=\"35\"{$action_str} {$extra} />\n";
+                               echo "<input name=\"", htmlspecialchars($name), "\" value=\"", htmlspecialchars($value), "\" size=\"35\"{$extra_str} />\n";
                                break;
                }
        }
index 81d5aae52af873cf9990d6770f7df3cfb77400c1..2b5191786a1e771006bd3552f805d5baa41bb613 100644 (file)
                        $misc->printTitle($lang['streditrow']);
                        $misc->printMsg($msg);
 
-                       $bAllowAC = ($conf['autocomplete'] != 'disable') ? TRUE : FALSE;
-                       if($bAllowAC) {
-                               $constraints = $data->getConstraints($_REQUEST['table']);
-                               $arrayLocals = array();
-                               $arrayRefs = array();
-                               $nC = 0;
-                               while(!$constraints->EOF) {
-                                       // The following RE will match a FK constrain with a single (quoted or not) referencing column. At the moment we don't support multicolumn FKs
-                                       preg_match('/^FOREIGN KEY \(("[^"]*"|[^\s",]*)\) REFERENCES (.*)\((.*)\)/i', $constraints->fields['consrc'], $matches);
-                                       if(!empty($matches)) {
-                                               // Strip possible quotes and save
-                                               $arrayLocals[$nC] = preg_replace('/"(.*)"/', '$1', $matches[1]);
-                                               $arrayRefs[$nC] = array(preg_replace('/"(.*)"/', '$1', $matches[2]), preg_replace('/"(.*)"/', '$1', $matches[3]));
-                                               $nC++;
-                                       }
-                                       $constraints->moveNext();
-                               }
-                       }
-
                        $attrs = $data->getTableAttributes($_REQUEST['table']);
                        $rs = $data->browseRow($_REQUEST['table'], $key);
-                       
+
+                       if (($conf['autocomplete'] != 'disable')) {
+                               $fksprops = $misc->getAutocompleteFKProperties($_REQUEST['table']);
+                               if ($fksprops !== false)
+                                       echo $fksprops['code'];
+                       }
+                       else $fksprops = false;
+
                        echo "<form action=\"display.php\" method=\"post\" id=\"ac_form\">\n";
                        $elements = 0;
                        $error = true;                  
 
                                $i = 0;
                                while (!$attrs->EOF) {
-                                       $szValueName = "values[{$attrs->fields['attname']}]";
-                                       $szEvents = '';
-                                       $szDivPH = '';
-                                       if($bAllowAC) {
-                                               $idxFound = array_search($attrs->fields['attname'], $arrayLocals);
-                                               // In PHP < 4.2.0 array_search returns NULL on failure
-                                               if ($idxFound !== NULL && $idxFound !== FALSE) {
-                                                       $szEvent = "makeAC('{$szValueName}',{$i},'{$arrayRefs[$idxFound][0]}','{$arrayRefs[$idxFound][1]}','{$_REQUEST['server']}','{$_REQUEST['database']}');";
-                                                       $szEvents = "onfocus=\"{$szEvent}\" onblur=\"hideAC();document.getElementById('ac_form').onsubmit=function(){return true;};\" onchange=\"{$szEvent}\" id=\"{$szValueName}\" onkeyup=\"{$szEvent}\" autocomplete=\"off\" class='ac_field'";
-                                                       $szDivPH = "<div id=\"fac{$i}_ph\"></div>";
-                                               }
-                                       }
+
                                        $attrs->fields['attnotnull'] = $data->phpBool($attrs->fields['attnotnull']);
                                        $id = (($i % 2) == 0 ? '1' : '2');
                                        
                                        else
                                                echo "&nbsp;</td>";
 
-                                       echo "<td id=\"aciwp{$i}\" style=\"white-space:nowrap;\">";
+                                       echo "<td id=\"row_att_{$attrs->fields['attnum']}\" style=\"white-space:nowrap;\">";
+
+                                       $extras = array();
+
                                        // 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']) {
-                                               echo $data->printField($szValueName, $rs->fields[$attrs->fields['attname']], $attrs->fields['type'], 
-                                                                                                       array('onChange' => 'elements[' . ($elements - 1) . '].checked = false;'),$szEvents) . $szDivPH;
+                                               $extras['onChange'] = 'elements[' . ($elements - 1) . '].checked = false;';
                                        }
-                                       else {
-                                               echo $data->printField($szValueName, $rs->fields[$attrs->fields['attname']], $attrs->fields['type'],array(),$szEvents) . $szDivPH;
+
+                                       if (($fksprops !== false) && isset($fksprops['byfield'][$attrs->fields['attnum']])) {
+                                               $extras['id'] = "attr_{$attrs->fields['attnum']}";
+                                               $extras['autocomplete'] = 'off';
                                        }
+
+                                       echo $data->printField("values[{$attrs->fields['attnum']}]", $rs->fields[$attrs->fields['attname']], $attrs->fields['type'], $extras);
+
                                        echo "</td>";
                                        $elements++;
                                        echo "</tr>\n";
                                        $attrs->moveNext();
                                }
                                echo "</table>\n";
-                               if($bAllowAC) {
-                                       echo '<script src="aciur.js" type="text/javascript"></script>';
-                                       echo "<div id=\"ac\"></div>";
-                               }
+
                                $error = false;
                        }
                        elseif ($rs->recordCount() != 1) {
                        echo "<p>";
                        if (!$error) echo "<input type=\"submit\" name=\"save\" value=\"{$lang['strsave']}\" />\n";
                        echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" />\n";
-                       if($bAllowAC) {
-                               $szChecked = $conf['autocomplete'] != 'default off' ? 'checked="checked"' : '';
-                               echo "<input type=\"checkbox\" name=\"no_ac\" id=\"no_ac\" onclick=\"rEB(this.checked);\" value=\"1\" {$szChecked} /><label for='no_ac' onmouseover='this.style.cursor=\"pointer\";'>{$lang['strac']}</label>\n";
+
+                       if($fksprops !== false) {
+                               if ($conf['autocomplete'] != 'default off')
+                                       echo "<input type=\"checkbox\" id=\"no_ac\" value=\"1\" checked=\"checked\" /><label for=\"no_ac\">{$lang['strac']}</label>\n";
+                               else
+                                       echo "<input type=\"checkbox\" id=\"no_ac\" value=\"0\" /><label for=\"no_ac\">{$lang['strac']}</label>\n";
                        }
+
                        echo "</p>\n";
                        echo "</form>\n";
-                       echo "<script>rEB(document.getElementById('no_ac').checked);</script>";
                }
                else {
                        if (!isset($_POST['values'])) $_POST['values'] = array();
index 7bbb3d9f3c359b4e54d2ac10ba6aebe07c1df0ab..469457192c23a9bc63bc5576b6a2c5d347d2d02e 100644 (file)
                global $data, $misc, $conf;
                global $lang;
 
-               $auto_complete = ($conf['autocomplete'] != 'disable');
-
                if ($confirm) {
                        $misc->printTrail('table');
                        $misc->printTitle($lang['strinsertrow'], 'pg.sql.insert');
                        $misc->printMsg($msg);
 
                        $attrs = $data->getTableAttributes($_REQUEST['table']);
-                       $fksprops = array(
-                               'byconstr' => array(),
-                               'byfield' => array(),
-                       );
-                       if($auto_complete) {
-                               $constrs = $data->getConstraintsWithFields($_REQUEST['table']);
-
-                               if (!$constrs->EOF) {
-                                       $conrelid = $constrs->fields['conrelid'];
-                                       while(!$constrs->EOF) {
-                                               if ($constrs->fields['contype'] == 'f') {
-                                                       if (!isset($fksprops['byconstr'][$constrs->fields['conid']])) {
-                                                               $fksprops['byconstr'][$constrs->fields['conid']] = array (
-                                                                       'confrelid' => $constrs->fields['confrelid'],
-                                                                       'f_table' => $constrs->fields['f_table'],
-                                                                       'f_schema' => $constrs->fields['f_schema'],
-                                                                       'pattnums' => array(),
-                                                                       'pattnames' => array(),
-                                                                       'fattnames' => array()
-                                                               );
-                                                       }
-
-                                                       $fksprops['byconstr'][$constrs->fields['conid']]['pattnums'][] = $constrs->fields['p_attnum'];
-                                                       $fksprops['byconstr'][$constrs->fields['conid']]['pattnames'][] = $constrs->fields['p_field'];
-                                                       $fksprops['byconstr'][$constrs->fields['conid']]['fattnames'][] = $constrs->fields['f_field'];
-
-                                                       if (!isset($fksprops['byfield'][$constrs->fields['p_attnum']]))
-                                                               $fksprops['byfield'][$constrs->fields['p_attnum']] = array();
-                                                       $fksprops['byfield'][$constrs->fields['p_attnum']] = $constrs->fields['conid'];
-                                               }
-                                               $constrs->moveNext();
-                                       }
-                                       
-                                       echo "<script type=\"text/javascript\">\n";
-                                       echo "var constrs = {};\n";
-                                       foreach ($fksprops['byconstr'] as $conid => $props) {
-                                               echo "constrs.constr_{$conid} = {\n";
-                                               echo 'pattnums: [', implode(',',$props['pattnums']), "],\n";
-                                               echo "f_table:\"", htmlentities($props['f_table']), "\",\n";
-                                               echo "f_schema:\"", htmlentities($props['f_schema']), "\",\n";
-                                               $_='';
-                                               foreach ($props['pattnames'] as $n) {
-                                                       $_.= ",'". htmlentities($n, ENT_QUOTES) ."'";
-                                               }
-                                               echo 'pattnames: [', substr($_, 1), "],\n";
-
-                                               $_='';
-                                               foreach ($props['fattnames'] as $n) {
-                                                       $_.= ",'". htmlentities($n, ENT_QUOTES) ."'";
-                                               }
-
-                                               echo 'fattnames: [', substr($_, 1), "]\n";
-                                               echo "};\n";
-                                       }
-
-                                       echo "var attrs = {};\n";
-                                       foreach ($fksprops['byfield'] as $attnum => $cstrs ) {
-                                               echo "attrs.attr_{$attnum} = {$fksprops['byfield'][$attnum]};\n";
-                                       }
-
-                                       echo "var table='", htmlentities($_REQUEST['table']), "';";
-                                       echo "var server='", htmlentities($_REQUEST['server']), "';";
-                                       echo "var database='", htmlentities($_REQUEST['database']), "';";
-                                       echo "</script>\n";
 
-                                       echo '<div id="fkbg"></div>';
-                                       echo '<div id="fklist"></div>';
-                               }
-                               else $auto_complete = false;
+                       if (($conf['autocomplete'] != 'disable')) {
+                               $fksprops = $misc->getAutocompleteFKProperties($_REQUEST['table']);
+                               if ($fksprops !== false)
+                                       echo $fksprops['code'];
                        }
+                       else $fksprops = false;
 
                        echo "<form action=\"tables.php\" method=\"post\" id=\"ac_form\">\n";
                        if ($attrs->recordCount() > 0) {
                                                echo "&nbsp;</td>";
                                        }
                                        echo "<td id=\"row_att_{$attrs->fields['attnum']}\" style=\"white-space:nowrap;\">";
-                                       if ($auto_complete && isset($fksprops['byfield'][$attrs->fields['attnum']])) {
-                                               echo $data->printField("values[{$attrs->fields['attnum']}]", $_REQUEST['values'][$attrs->fields['attnum']],
-                                                       'fktype'/*force FK*/,array(), "id=\"attr_{$attrs->fields['attnum']}\" autocomplete=\"off\"");
+                                       if (($fksprops !== false) && isset($fksprops['byfield'][$attrs->fields['attnum']])) {
+                                               echo $data->printField("values[{$attrs->fields['attnum']}]", $_REQUEST['values'][$attrs->fields['attnum']], 'fktype'/*force FK*/,
+                                                       array(
+                                                               'id' => "attr_{$attrs->fields['attnum']}",
+                                                               'autocomplete' => 'off'
+                                                       )
+                                               );
                                        }
                                        else {
-                                               echo $data->printField("values[{$attrs->fields['attnum']}]", $_REQUEST['values'][$attrs->fields['attnum']],
-                                                       $attrs->fields['type'],array());
+                                               echo $data->printField("values[{$attrs->fields['attnum']}]", $_REQUEST['values'][$attrs->fields['attnum']], $attrs->fields['type']);
                                        }
                                        echo "</td>\n";
                                        echo "</tr>\n";
                                        $attrs->moveNext();
                                }
                                echo "</table>\n";
-                               if($auto_complete) {
-                                       echo "<script src=\"libraries/js/jquery.js\" type=\"text/javascript\"></script>";
-                                       echo "<script src=\"js/ac_insert_row.js\" type=\"text/javascript\"></script>";
-                               }
 
                                if (!isset($_SESSION['counter'])) { $_SESSION['counter'] = 0; }
 
                                echo "<input type=\"submit\" name=\"insertandrepeat\" value=\"{$lang['strinsertandrepeat']}\" />\n";
                                echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" />\n";
                                
-                               if($auto_complete) {
+                               if($fksprops !== false) {
                                        if ($conf['autocomplete'] != 'default off')
                                                echo "<input type=\"checkbox\" id=\"no_ac\" value=\"1\" checked=\"checked\" /><label for=\"no_ac\">{$lang['strac']}</label>\n";
                                        else