* Copyright (c) 2001-2002 Jim Kraai * Versions 5.0 and higher developed by Ondrej Jombik * Copyright (c) 2002 Platon SDG, http://www.platon.sk/ * All rights reserved. * * See README file for more information about this software. * See COPYING file for license information. * * Download the latest version from * http://www.platon.sk/projects/phpMyEdit/ */ /* $Platon: phpMyEdit/phpMyEdit.class.php,v 1.37 2002/12/14 04:40:55 nepto Exp $ */ /* phpMyEdit intro {{{ */ /* This is a generic table editing program. The table and fields to be edited are defined in the calling program. This program works in three passes. Pass 1 (the last part of the program) displays the selected MySQL table in a scrolling table on the screen. Radio buttons are used to select a record for editing or deletion. If the user chooses Add, Change, or Delete buttons, Pass 2 starts, displaying the selected record. If the user chooses the Save button from this screen, Pass 3 processes the update and the display returns to the original table view (Pass 1). version 3.5 - 06-May-01 important variables passed between calls to this program $fm first record to display $inc no of records to display (SELECT ... LIMIT $fm,$inc) $fl is the filter row displayed (boolean) $rec unique id of record selected for editing $qf0,.. value of filter for column 0 $qfn value of all filters used during the last pass $sfn sort field number (- = descending sort order) $operation operation to do: Add, Change, Delete $message informational message to print $filter filter query $sw filter display/hide button $prev, $next navigation buttons $labels narrative for buttons, etc Conversion to PHP Classes by Pau Aliagas (pau@newtral.com) ToDo: 'Copy' button Aggregates: nonworking code commented out in list_table() doesn't work yet Query Building: Multi-Part Date Handling: Finish converting date handling to internal date handling functions Abstract date field gathering to get rid of _many_ redundant lines of code There was some kludged fix for dateformat'ting where '%'s are removed Better support for more date format macros Better documentation for valid date format macros Multi-Language support: Finish implementing language labels Use browser-supplied language if available Allow programmer override in setup.php generated .inc file Add 'Search' and 'Go!' to labels array Data Validation: Expand JS field validation to match JS regexes Create PHP field validation to match PHP regexes Change Tracking/Notification: Add change notification (via mail()) support Don't die if mail() not available CSS: Document & solicit feedback to standardize class names Even/Odd Coloring: Move to CSS Put values in setup.php generated file Timer Class: Solicit user input whether to put timer class into this lib */ /* }}} */ if (@include_once dirname(__FILE__).'/timer.class') { $phpMyEdit_timer = new timerClass(); } if (! function_exists('array_search')) { /* {{{ */ function array_search($needle, $haystack) { foreach ($haystack as $key => $value) { if ($needle == $value) return $key; } return false; } } /* }}} */ class phpMyEdit { // Class variables // {{{ var $hn; // hostname var $un; // user name var $pw; // password var $db; // database var $tb; // table var $dbh; // database handle var $key; // Name of field which is the unique key var $key_type; // Type of key field (int/real/string/date etc) var $key_delim; var $inc; // no of records to display (SELECT ... LIMIT $fm, $inc) var $fm; // first record to display var $fl; // is the filter row displayed (boolean) var $options; // Options for users: A(dd) C(hange) D(elete) F(ilter) V(iew) co(P)y U(nsorted) var $fdd; // field definitions var $qfn; // value of all filters used during the last pass var $sfn; // sort field number (- = descending sort order) var $rec; // no. of record selected for editing var $prev; // navigation buttons var $next; var $sw; // filter display/hide button var $labels; // labels for buttons, etc (multilingual) var $cgi; // CGI variable features array var $url; // URL array var $operation; // operation to do: Add, Change, Delete var $message; // informational message to print var $saveadd; var $moreeadd; var $savechange; var $savedelete; var $fds; // sql field names var $num_fds; // number of fields var $notify; // change notification e-mail adresses var $logtable; // name of optional logtable var $navigation; // navigation style // }}} function debug_var($name, $val) /* {{{ */ { if (is_array($val) || is_object($val)) { echo "
$name\n";
			ob_start();
			//print_r($val);
			var_dump($val);
			$content = ob_get_contents();
			ob_end_clean();
			echo htmlspecialchars($content);
			echo "
\n"; } else { echo 'debug_var()::'.htmlspecialchars($name).'::' .htmlspecialchars($val).'::'."
\n"; } } /* }}} */ function myquery($qry, $line = 0, $debug = 0) /* {{{ */ { global $debug_query; if ($debug_query || $debug) { $line = intval($line); echo '

MySQL query at line '.$line.'

'.htmlspecialchars($qry).'
'."\n"; } $this->elog("qry: $qry",$line); $ret = @mysql_db_query($this->db, $qry, $this->dbh); if (! $ret) { $this->elog(mysql_errno($this->dbh).': '.mysql_error($this->dbh).' in '.$qry, __LINE__); } return $ret; } /* }}} */ function encode($field,$str) /* {{{ */ { if (isset($field['dbencode'])) { return eval( 'return ' .$field['dbencode'] .'(\''.$str.'\');'); } else { return $str; } } /* }}} */ function elog($str,$line) /* {{{ */ { error_log(__FILE__.":$line::\n$str",0); return true; } /* }}} */ function make_language_labels($language) /* {{{ */ { // just try the first language and variant // this isn't content-negotiation rfc compliant $language = strtoupper(substr($language,0,5)); // try the full language w/ variant $file = $this->dir['lang'].'PME.lang.'.$language.'.inc'; if (! file_exists($file)) { // try the language w/o variant $file = $this->dir['lang'].'PME.lang.'.substr($language,0,2).'.inc'; } if (! file_exists($file)) { // default to classical English $file = $this->dir['lang'].'PME.lang.EN.inc'; } $ret = @include($file); if (! is_array($ret)) { return $ret; } $small = array( 'Search' => 'v', 'Hide' => '^', 'Clear' => 'X', 'Query' => htmlspecialchars('>')); if ((!$this->nav_text_links() && !$this->nav_graphic_links()) || !isset($ret['Search']) || !isset($ret['Query']) || !isset($ret['Hide']) || !isset($ret['Clear'])) { foreach ($small as $key => $val) { $ret[$key] = $val; } } return $ret; } /* }}} */ function set_values_from_table($field_num, $prepend = '') /* {{{ */ { /* echo "$field_num, "; var_dump($prepend); echo '
';
		   var_dump($this->fdd);
		   echo '
'; */ if($this->fdd[$field_num]['values']['db']) { $db = $this->fdd[$field_num]['values']['db']; } else { $db = $this->db; } $table = $this->fdd[$field_num]['values']['table']; $key = $this->fdd[$field_num]['values']['column']; $desc = $this->fdd[$field_num]['values']['description']; $qparts['type'] = 'select'; if ($table) { $qparts['select'] = 'DISTINCT '.$key; if ($desc) { //- $qparts['select'] .= ','.$desc; //- $qparts['orderby'] = $desc; // Changes 08/08/02 Shaun Johnston if (is_array($desc)) { $qparts['select'] .= ',CONCAT('; // ) $num_cols = sizeof($desc['columns']); for ($i = 0; $i <= $num_cols; $i++) { $qparts['select'] .= $desc['columns'][$i]; if ($desc['divs'][$i]) { $qparts['select'] .= ',"'.$desc['divs'][$i].'"'; } if ($i < ($num_cols - 1)) { $qparts['select'] .= ','; } } $qparts['select'] .= ') AS select_alias_'.$field_num; $qparts['orderby'] = empty($desc['orderby']) ? 'select_alias_'.$field_num : $desc['orderby']; } else { $qparts['select'] .= ','.$desc; $qparts['orderby'] = $desc; } } else { if ($key) { $qparts['orderby'] = $key; } } //$qparts['from'] = "$db.$table.$sel; $qparts['from'] = "$db.$table"; $qparts['where'] = $this->fdd[$field_num]['values']['filters']; if ($this->fdd[$field_num]['values']['orderby']) { $qparts['orderby'] = $this->fdd[$field_num]['values']['orderby']; } } else { /* simple value extraction */ $qparts['select'] = 'DISTINCT '.$this->fds[$field_num]; $qparts['from'] = $this->db.'.'.$this->tb; } $values = array(); $res = $this->myquery($this->query_make($qparts), __LINE__); while ($row = @mysql_fetch_array($res, MYSQL_NUM)) { $values[$row[0]] = $desc ? $row[1] : $row[0]; } $values2 = $this->fdd[$field_num]['values2']; is_array($values2) && $values = $values2 + $values; is_array($prepend) && $values = $prepend + $values; /* old wrong prepending -- REMOVE ME at December 2002 if (is_array($prepend)) { $values[$prepend[0]] = $prepend[1]; } */ return $values; } /* }}} */ /* * get the table/field name */ function fqn($field, $use_qfx = false, $dont_desc = false, $dont_cols = false) /* {{{ */ { preg_match('/^\d*$/', $field) || $field = array_search($field, $this->fds); // on copy/change always use simple key retrieving if ($this->add_operation() || $this->copy_operation() || $this->change_operation()) { $ret = 'Table0.'.$this->fds[$field]; } else { if (isset($this->fdd[$field]['expression'])) { $ret = $this->fdd[$field]['expression']; } elseif ($this->fdd[$this->fds[$field]]['values']['description'] && ! $dont_desc) { // Changed 06/08/02 Shaun Johnston $desc = $this->fdd[$this->fds[$field]]['values']['description']; if (is_array($desc)) { $ret = 'CONCAT('; // ) $num_cols = sizeof($desc['columns']); for ($i = 0; $i < $num_cols; $i++) { $ret .= 'JoinTable'.$field.'.'.$desc['columns'][$i]; if ($desc['divs'][$i]) { $ret .= ',"'.$desc['divs'][$i].'"'; } if ($i < ($num_cols - 1)) { $ret .= ','; } } $ret .= ')'; } else { $ret = 'JoinTable'.$field.'.'.$this->fdd[$this->fds[$field]]['values']['description']; } // TODO: remove me } elseif (0 && $this->fdd[$this->fds[$field]]['values']['column'] && ! $dont_cols) { $ret = 'JoinTable'.$field.'.'.$this->fdd[$this->fds[$field]]['values']['column']; } else { $ret = 'Table0.'.$this->fds[$field]; } // TODO: not neccessary, remove me! if (is_array($this->fdd[$this->fds[$field]]['values2'])) { } } // what to do with $format XXX if ($use_qfx) $ret = 'qf'.$field; // return the value return $ret; } /* }}} */ function create_column_list() /* {{{ */ { $fields = array(); for ($k = 0; $k < $this->num_fds; $k++) { if (! $this->displayed[$k] && $k != $this->key_num) continue; if ($this->col_is_date($k)) { //$fields[] = 'UNIX_TIMESTAMP('.$this->fqn($k).') AS qf'.$k; //$fields[] = 'DATE_FORMAT('.$this->fqn($k).',"%Y%m%d%H%i%s") AS qf'.$k; $fields[] = $this->fqn($k).' AS qf'.$k; } else { $fields[] = $this->fqn($k).' AS qf'.$k; if ($this->col_has_values($k)) { $fields[] = $this->fqn($k, false, true, true).' AS qf'.$k.'_idx'; } //echo '[['.$this->fqn($k).' AS qf'.$k.']]
'; } } return join(',',$fields); } /* }}} */ function query_make($parts) /* {{{ */ { foreach ($parts as $k => $v) { $parts[$k] = trim($parts[$k]); } switch ($parts['type']) { case 'select': $ret = 'SELECT '; if ($parts['DISTINCT']) $ret .= 'DISTINCT '; $ret .= $parts['select']; $ret .= ' FROM '.$parts['from']; if ($parts['where'] != '') $ret .= ' WHERE '.$parts['where']; if ($parts['groupby'] != '') $ret .= ' GROUP BY '.$parts['groupby']; if ($parts['having'] != '') $ret .= ' HAVING '.$parts['having']; if ($parts['orderby'] != '') $ret .= ' ORDER BY '.$parts['orderby']; if ($parts['limit'] != '') $ret .= ' LIMIT '.$parts['limit']; if ($parts['procedure'] != '') $ret .= ' PROCEDURE '.$parts['procedure']; break; case 'update': $ret = 'UPDATE '.$parts['table']; $ret .= ' SET '.$parts['fields']; if ($parts['where'] != '') $ret .= ' WHERE '.$parts['where']; break; case 'insert': $ret = 'INSERT INTO '.$parts['table']; $ret .= ' VALUES '.$parts['values']; break; case 'delete': $ret = 'DELETE FROM '.$parts['table']; if ($parts['where'] != '') $ret .= ' WHERE '.$parts['where']; break; default: die('unknown query type'); break; } return $ret; } /* }}} */ function create_join_clause() /* {{{ */ { $tbs[] = $this->tb; $join = $this->tb.' AS Table0'; for ($k = 0,$numfds = sizeof($this->fds); $k<$numfds; $k++) { $field = $this->fds[$k]; if($this->fdd[$field]['values']['db']) { $db = $this->fdd[$field]['values']['db']; } else { $db = $this->db; } $table = $this->fdd[$field]['values']['table']; $id = $this->fdd[$field]['values']['column']; $desc = $this->fdd[$field]['values']['description']; if ($desc != '' && $id != '') { $alias = 'JoinTable'.$k; if (!in_array($alias,$tbs)) { $join .= " LEFT OUTER JOIN $db.". $table. ' AS '.$alias. ' ON '.$alias. '.'.$id. '='.'Table0.'.$field; $tbs[]=$alias; } } } return $join; } /* }}} */ function make_where_from_query_opts($qp='') /* {{{ */ { if ($qp == '') $qp = $this->query_opts; $where = array(); foreach ($qp as $field => $ov) { $where[] = sprintf('%s %s %s', $field, $ov['oper'], $ov['value']); } // Add any coder specified filters if ($this->filters) $where[] = '('.$this->filters.')'; if (count($where) > 0) return join(' AND ',$where); return false; } /* }}} */ function make_text_where_from_query_opts($qp='') /* {{{ */ { if ($qp == '') $qp = $this->query_opts; $where = array(); foreach ($qp as $field => $ov) { $where[] = sprintf('%s %s %s', $field, $ov['oper'], $ov['value']); } if (count($where) > 0) return str_replace('%', '*', join(' AND ',$where)); return false; } /* }}} */ /* * functions for get/post/query args */ function gather_post_vars() /* {{{ */ { global $HTTP_POST_VARS; foreach ($HTTP_POST_VARS as $key => $val) { if ($val != '' && $val != '*') { $pv[$key] = $val; } } $this->pv = $pv; } /* }}} */ function gather_query_opts() /* {{{ */ { // gathers query options into an array, $this->query_opts $query_opts = array(); $qo = array(); for ($k = 0; $k < $this->num_fds; $k++) { $l = 'qf'.$k; $lc = 'qf'.$k.'_comp'; $$l = $this->get_cgi_var($l); $$lc = $this->get_cgi_var($lc); $m = $this->web2plain($$l); // get the field name and value $mc = $this->web2plain($$lc); // get the comparison operator for numeric/date types $type = $this->fdd[$k]['type']; if ($m == '') { continue; } if (is_array($m)) { // multiple selection has been used if (!in_array('*',$m)) { // one '*' in a multiple selection is all you need $qf_op = ''; foreach (array_keys($m) as $key) { if ($qf_op == '') { $qf_op = 'IN'; $qf_val = "'".addslashes($m[$key])."'"; $afilter =" IN ('".addslashes($m[$key])."'"; } else { $afilter = $afilter.",'".addslashes($m[$key])."'"; $qf_val .= ",'".addslashes($m[$key])."'"; } } $afilter = $afilter.')'; // XXX: $dont_desc and $dont_cols hack $dont_desc = isset($this->fdd[$k]['values']['description']); $dont_cols = isset($this->fdd[$k]['values']['column']); $qo[$this->fqn($k, false, $dont_desc, $dont_cols)] = array('oper' => $qf_op, 'value' => '('.$qf_val.')'); } } else { $afilter = addslashes($m); if ($afilter != '*') { /* XXX: This is ugly fqn() hack. We must pass third $dont_desc parameter to fqn() method, as far as we want to return not description column, but ID one. */ if ($this->fdd[$k]['values']['description']) { // DEBUG // echo htmlspecialchars(' k = '.$k.' | fqn($k) = '.$this->fqn($k, false, true)); $qo[$this->fqn($k, false, true, true)] = array('oper' => '=', 'value' => "'".$afilter."'"); } elseif ($this->fdd[$k]['values']['column']) { $qo[$this->fqn($k, false, true, true)] = array('oper' => '=', 'value' => "'".$afilter."'"); } elseif ($this->col_is_string($k)) { // massage the filter for a string comparison if (($afilter != '') AND ($afilter != '*')) { $afilter = '%'.str_replace('*', '%', $afilter).'%'; $qo[$this->fqn($k)] = array('oper' => 'like', 'value' => "'".$afilter."'"); } } elseif ($this->col_is_number($k) && ($$lc != '')) { if ($$lc != '') { $qo[$this->fqn($k)] = array('oper' => $mc, 'value' => $afilter); } } elseif ($this->col_is_date($k)) { #if ($$lc != '') { # $val = $this->gather_date_fields_into_type($$l,$type); # $val = $this->mdate_set(date($this->mdate_masks[$type],$this->mdate_getFromPost($k)),$type); # $val = $this->mdate_getFromPost($k); # if ($val != '') { # $qo[$this->fqn($k)] = # array( 'oper' => $mc, 'value' => '"'.$val.'"'); # } #} # massage the filter for a string comparison if (($afilter != '') AND ($afilter != '*')) { $afilter = '%'.str_replace ('*', '%', $afilter).'%'; $qo[$this->fqn($k)] = array('oper' => 'like', 'value' => "'".$afilter."'"); } } elseif($this->col_has_values($k)) { //debug_var('col_is_string',$this->fdd[$k]['name'].'::'.$this->fdd[$k]['type']); $qo[$this->fqn($k)] = array( 'oper' => '=', 'value' => "'".$afilter."'"); } else { // unknown (to mysql/php interface) field type // message the filter for a string comparison $afilter = '%'.str_replace ('*', '%', $afilter).'%'; $qo[$this->fqn($k)] = array('oper' => 'like', 'value' => "'".$afilter."'"); } } } } // for $this->query_opts = $qo; } // gather_query_opts /* }}} */ function gather_get_vars() /* {{{ */ { global $HTTP_SERVER_VARS; $vals = array(); $parts = split('&',$HTTP_SERVER_VARS['QUERY_STRING']); if (count($parts) > 0) { foreach ($parts as $part) { list($key,$val) = split('=',$part,2); $vals[$key] = $val; } } $this->get_opts = $vals; } /* }}} */ function unify_opts() /* {{{ */ { $all_opts = array(); if (count($this->qo) > 0) { foreach ($this->qo as $key=>$val) $all_opts[$key] = $val; } if (count($this->pv) > 0) { foreach ($this->pv as $key=>$val) $all_opts[$key] = $val; } if (count($this->get_opts) > 0) { foreach ($this->get_opts as $key=>$val) $all_opts[$key] = $val; } $this->all_opts = $all_opts; } /* }}} */ /* * type functions */ function col_is_date($k) { return in_array($this->fdd[$k]['type'], $this->dateTypes ); } function col_is_number($k) { return in_array($this->fdd[$k]['type'], $this->numberTypes); } function col_is_string($k) { return in_array($this->fdd[$k]['type'], $this->stringTypes); } function col_is_set($k) { return $this->fdd[$k]['type'] == 'set'; } function col_has_values($k) { return isset($this->fdd[$k]['values']) || isset($this->fdd[$k]['values2']); } /* * functions for indicating whether navigation style is enabled */ function nav_buttons() { return stristr($this->navigation, 'B'); } function nav_text_links() { return stristr($this->navigation, 'T'); } function nav_graphic_links() { return stristr($this->navigation, 'G'); } function nav_up() { return stristr($this->navigation, 'U'); } function nav_down() { return stristr($this->navigation, 'D'); } /* * functions for indicating whether operations are enabled */ function initial_sort_suppressed() { return (stristr ($this->options, 'I')); } function add_enabled() { return stristr($this->options, 'A'); } function change_enabled() { return stristr($this->options, 'C'); } function delete_enabled() { return stristr($this->options, 'D'); } function filter_enabled() { return stristr($this->options, 'F'); } function view_enabled() { return stristr($this->options, 'V'); } function copy_enabled() { return stristr($this->options, 'P') && $this->add_enabled(); } function hidden($k) { return stristr($this->fdd[$k]['options'],'H'); } function password($k) { return stristr($this->fdd[$k]['options'],'W'); } function readonly($k) { return stristr($this->fdd[$k]['options'],'R') || $this->fdd[$k]['expression']; } function add_operation() { return $this->operation == $this->labels['Add'] && $this->add_enabled(); } function change_operation() { return $this->operation == $this->labels['Change'] && $this->change_enabled(); } function copy_operation() { return $this->operation == $this->labels['Copy'] && $this->copy_enabled(); } function delete_operation() { return $this->operation == $this->labels['Delete'] && $this->delete_enabled(); } function view_operation() { return $this->operation == $this->labels['View'] && $this->view_enabled(); } function filter_operation() { return $this->fl && $this->filter_enabled(); } function next_operation() { return $this->next == $this->labels['Next']; } function prev_operation() { return $this->prev == $this->labels['Prev']; } function is_values2($k, $val = 'X') /* {{{ */ { return $val === null || (isset($this->fdd[$k]['values2']) && !isset($this->fdd[$k]['values']['table'])); } /* }}} */ function processed($k) /* {{{ */ { $options = @$this->fdd[$k]['options']; if (! isset($options)) return true; return /* empty($options) || */ // XXX: woof woof woof hack, probably brokes BC, but here BC == BB (bad behaviour) ($this->saveadd == $this->labels['Save'] && stristr($options, 'A')) || ($this->moreadd == $this->labels['More'] && stristr($options, 'A')) || ($this->savechange == $this->labels['Save'] && stristr($options, 'C')) || ($this->morechange == $this->labels['Apply'] && stristr($options, 'C')) || ($this->savechange == $this->labels['Save'] && stristr($options, 'P')) || ($this->savedelete == $this->labels['Save'] && stristr($options, 'D')); } /* }}} */ function displayed($k) /* {{{ */ { if (is_numeric($k)) { $k = $this->fds[$k]; } $options = $this->fdd[$k]['options']; if (! isset($options)) return true; #if ($this->hidden($k)) # return false; return ($this->add_operation() && stristr($options, 'A')) || ($this->view_operation() && stristr($options, 'V')) || ($this->change_operation() && stristr($options, 'C')) || ($this->copy_operation() && stristr($options, 'P')) || ($this->delete_operation() && stristr($options, 'D')) || ((stristr($options,'L') || ($this->filter_operation() && stristr($options, 'F'))) && ! $this->add_operation() && ! $this->view_operation() && ! $this->change_operation() && ! $this->copy_operation() && ! $this->delete_operation()); } /* }}} */ /* * Create JavaScripts */ function create_javascripts() /* {{{ */ { /* Need a lot of work in here using something like: $fdd['fieldname']['validate']['js_regex']='/something/'; $fdd['fieldname']['validate']['php_regex']='something'; */ $page_name = htmlspecialchars($this->page_name); if ($this->add_operation() || $this->change_operation()) { $required_ar = array(); for ($k = 0; $k < $this->num_fds; $k++) { if ($this->displayed[$k] && $this->fdd[$k]['required'] && ! $this->col_has_values($k)) { $required_ar[] = $k; if (isset($this->fdd[$k]['regex']['js'])) { /* TODO: Use a javascript regex to validate it */ } } } if (count($required_ar) > 0) { echo '' . "\n"; echo '
'."\n"; return true; } } echo ''."\n"; return true; } /* }}} */ /* * Display functions */ function display_add_record() /* {{{ */ { if (0) { // XXX: WTF? echo ''."\n"; echo 'Field'."\n"; echo 'Value'."\n"; if ($this->guidance) echo 'Guidance'."\n"; echo ''."\n"; } for ($k = 0; $k < $this->num_fds; $k++) { if (! $this->displayed[$k]) { continue; } echo ''."\n"; echo ''.$this->fdd[$k]['name'].''."\n"; if ($this->col_has_values($k) && !$this->readonly($k)) { echo '' ."\n"; $vals = isset($this->fdd[$k]['values']['table']) ? $this->set_values_from_table($k) : (array) $this->fdd[$k]['values2'] + (array) $this->fdd[$k]['values']; echo $this->htmlSelect($this->fds[$k], $vals, '', $this->col_is_set($k)); echo ''."\n"; } elseif (isset ($this->fdd[$k]['textarea']) && !$this->readonly($k)) { echo ''."\n"; } else { // Simple edit box required echo ''; $size_ml_props = ''; if ($this->fdd[$k]['type'] != 'blob') { $maxlen = intval($this->fdd[$k]['maxlen']); $maxlen > 0 || $maxlen = 300; $size = min($maxlen, 60); $size && $size_ml_props .= ' size="'.$size.'"'; $maxlen && $size_ml_props .= ' maxlength="'.$maxlen.'"'; } if ($this->col_is_string($k) || $this->col_is_number($k)) { // string type echo 'readonly($k)?'disabled ':'') .' name="'.$this->fds[$k].'"'.$size_ml_props.' value="' .$this->htmlDisplay($this->fdd[$k],$this->fdd[$k]['default'], false, false, false) .'">'; } elseif ($this->col_is_date($k)) { // date type, get date components //if ($this->fdd[$k]['default']) // $value = $this->mdate_set($this->fdd[$k]['default'],$this->fdd[$k]['type']); //$value = time(); //echo $this->mdate_disperse($k,$value,true); // string type echo 'readonly($k)?'disabled ':'') .' name="'.$this->fds[$k].'"'.$size_ml_props.' value="' .$this->htmlDisplay($this->fdd[$k],$this->fdd[$k]['default'], false, false, false) .'">'; } else { // unknown type echo 'readonly($k)?'disabled ':'') .' name="'.$this->fds[$k].'" value="' .$this->htmlDisplay($this->fdd[$k],$this->fdd[$k]['default'], false, false, false) .'">'; } echo ''; } if ($this->guidance) { if ($this->fdd[$k]['help']) echo ''.$this->fdd[$k]['help'].''."\n"; else echo ' '."\n"; } echo ''."\n"; } } /* }}} */ function display_copy_change_delete_record() /* {{{ */ { /* * For delete or change: SQL SELECT to retrieve the selected record */ $qparts['type'] = 'select'; $qparts['select'] = $this->create_column_list(); $qparts['from'] = $this->create_join_clause(); $qparts['where'] = '('.$this->fqn($this->key).'=' .$this->key_delim.$this->rec.$this->key_delim.')'; $res = $this->myquery($this->query_make($qparts),__LINE__); if (! ($row = @mysql_fetch_array($res, MYSQL_ASSOC))) { return false; } for ($k = 0; $k < $this->num_fds; $k++) { if ($this->copy_operation() || $this->change_operation()) { if ($this->hidden($k)) { if ($k != $this->key_num) { echo $this->htmlHidden($this->fds[$k], $this->htmlDisplay($this->fdd[$k], $row["qf$k"], false, true, false)); } continue; } if (! $this->displayed[$k]) { continue; } echo ''; echo ''.$this->fdd[$k]['name'].''."\n"; /* There are two possibilities of readonly fields handling: 1. Display plain text 2. Display disabled input field In all cases particular readonly field will NOT be saved. */ if (0 && $this->readonly($k)) { echo $this->display_delete_field($row, $k); } elseif ($this->password($k)) { echo $this->display_password_field($row, $k); } else { echo $this->display_change_field($row, $k); } if ($this->guidance) { if ($this->fdd[$k]['help']) echo ''.$this->fdd[$k]['help'].''."\n"; else echo ' '."\n"; } echo ''."\n"; } elseif ($this->delete_operation() || $this->view_operation()) { if (! $this->displayed[$k]) { continue; } echo ''."\n"; echo ''.$this->fdd[$k]['name'].''."\n"; if ($this->password($k)) { echo ''.$this->labels['hidden'].''; } else { $this->display_delete_field($row, $k); } if ($this->guidance) { if ($this->fdd[$k]['help']) echo ''.$this->fdd[$k]['help'].''."\n"; else echo ' '."\n"; } echo ''."\n"; } } } /* }}} */ function display_change_field($row, $k) /* {{{ */ { echo ''."\n"; if ($this->col_has_values($k) && !$this->readonly($k)) { $vals = isset($this->fdd[$k]['values']['table']) ? $this->set_values_from_table($k) : (array) $this->fdd[$k]['values2'] + (array) $this->fdd[$k]['values']; echo $this->htmlSelect($this->fds[$k], $vals, $row["qf$k"], $this->col_is_set($k)); } elseif (isset($this->fdd[$k]['textarea']) && !$this->readonly($k)) { echo ''."\n"; } else { $size_ml_props = ''; if ($this->fdd[$k]['type'] != 'blob') { $maxlen = intval($this->fdd[$k]['maxlen']); $maxlen > 0 || $maxlen = 300; $size = min($maxlen, 60); $size && $size_ml_props .= ' size="'.$size.'"'; $maxlen && $size_ml_props .= ' maxlength="'.$maxlen.'"'; } if ($this->col_is_string($k) || $this->col_is_number($k)) { // string type echo 'readonly($k)?'disabled ':'') .'name="'.$this->fds[$k].'" value="' .$this->htmlDisplay($this->fdd[$k], $row["qf$k"], false, true, false) .'" '.$size_ml_props.'>'; } elseif ($this->col_is_date($k)) { # date type, get date components #$value = $this->mdate_from_mysql($row[$k]); #if ($this->readonly($k)) { # $mask = $this->fdd[$k]['datemask']; # if (! $mask) # $mask = $this->mdate_masks[$this->fdd[$k]['type']]; # echo $this->mdate_format($value,$mask); #} else { # echo $this->mdate_disperse($k,$value,true); #} // string type echo 'readonly($k)?'disabled ':'') .'name="'.$this->fds[$k].'" value="' .$this->htmlDisplay($this->fdd[$k], $row["qf$k"], false, true, false) .'" '.$size_ml_props.'>'; } else { // unknown type echo 'readonly($k)?'disabled ':'') .'name="'.$this->fds[$k].'" value="' .$this->htmlDisplay($this->fdd[$k],$row["qf$k"], false, true, false).'">'; } echo "\n"; } // if elseif else echo ''."\n"; } /* }}} */ function display_password_field($row, $k) /* {{{ */ { echo ''."\n"; $size_ml_props = ''; if ($this->fdd[$k]['type'] != 'blob') { $maxlen = intval($this->fdd[$k]['maxlen']); $maxlen > 0 || $maxlen = 300; $size = min($maxlen, 60); $size && $size_ml_props .= ' size="'.$size.'"'; $maxlen && $size_ml_props .= ' maxlength="'.$maxlen.'"'; } echo 'readonly($k)?'disabled ':'') .'name="'.$this->fds[$k].'" value="' .$this->htmlDisplay($this->fdd[$k], $row["qf$k"], false, true, false) .'" '.$size_ml_props.'>'; echo ''."\n"; } /* }}} */ function display_delete_field($row, $k) /* {{{ */ { echo ''; if ($this->is_values2($k, $row["qf$k"])) { echo nl2br($this->htmlDisplay($k, $this->fdd[$k]['values2'][$row['qf'.$k.'_idx']], true, true, true, false)); } else { echo nl2br($this->htmlDisplay($this->fdd[$k], $row["qf$k"])); } echo ''."\n"; } /* }}} */ /** * Creates HTML hidden input element * * @param name element name * @param value value */ function htmlHidden($name, $value) /* {{{ */ { // Here are purpously not used htmlspecialchars() return ''."\n"; } /* }}} */ /** * Creates HTML select element (tag) * * @param name element name * @param kv_array key => value array * @param selected selected key (it can be single string, array of * keys or multiple values separated by comma * @param multiple bool for mulptiple selection * @param nat_sort bool for natural sorting */ function htmlSelect($name, $kv_array, $selected = null, $multiple = false, $nat_sort = false) /* {{{ */ { $ret = ''; return $ret; } /* }}} */ /** * Returns HTML text * * @param field field name/number * @param str str to print * @param usemask flag if field mask should be used * @param usecodec flag if field codec should be used * @param disallow_empty flag if empty string is forbidden on output * @param escape flag if output should be HTML escaped */ function htmlDisplay($field, $str, /* ...) {{{ */ $usemask = true, $usecodec = true, $disallow_empty = true, $escape = true) { // if there's a field mask, use it as first arg to sprintf if (isset($field['mask']) && $usemask) { $str = sprintf($field['mask'], $str); } // if db codec is in effect, use it if ($usecodec && isset($field['dbdecode'])) { $str = eval('return '.$field['dbdecode'].'(\''.$str.'\');'); } if ($escape) { $str = htmlspecialchars($str); } if ($disallow_empty) { strlen($str) <= 0 && $str = ' '; } return $str; } /* }}} */ /* Function extracted from phpPlatonLib http://www.platon.sk/projects/phpPlatonLib/ */ function write_origvars_html($origvars, $default_value = null) /* {{{ */ { foreach (explode('&', $origvars) as $param) { $parts = explode('=', $param, 2); if (! isset($parts[1]) && isset($default_value)) $parts[1] = $default_value; if (strlen($parts[0]) <= 0) continue; echo '\n"; } return true; } /* }}} */ function get_sfn_cgi_vars($alternative_sfn = null) /* {{{ */ { if ($alternative_sfn == null) { // FAST! (cached return value) static $ret = null; $ret == null && $ret = $this->get_sfn_cgi_vars($this->sfn); return $ret; } $ret = ''; $i = 0; foreach ($alternative_sfn as $val) { $ret != '' && $ret .= '&'; $ret .= "sfn[$i]=$val"; $i++; } return $ret; } /* }}} */ function get_qf_hidden_fields() /* {{{ */ { /* If the filter input boxes are not displayed, we need to preserve the filter by its emulaion. */ $this->qfn = ''; $hidden_qfs = ''; for ($k = 0; $k < $this->num_fds; $k++) { $l = 'qf'.$k; $lc = 'qf'.$k.'_comp'; $$l = $this->get_cgi_var($l); $$lc = $this->get_cgi_var($lc); $m = $this->web2plain($$l); // get the field name and value $mc = $this->web2plain($$lc); // get the comparison operator for numeric/date types if (!isset($m)) { continue; } if (is_array($m)) { // multiple selection has been used if (!in_array('*',$m)) {// one '*' in a multiple selection is all you need for ($n=0; $nplain2web($m[$n]) != '') { $this->qfn = $this->qfn.'&qf'.$k.'['.$n.']=' .$this->plain2web($m[$n]); } $hidden_qfs .= ''."\n"; } } } else { // query field comparison operator (if any) if ($this->plain2web($mc) != '') { $this->qfn = $this->qfn.'&qf'.$k.'_comp='.$this->plain2web($mc); $hidden_qfs .= ''."\n"; } // preserve query field & value if ($this->plain2web($m) != '') { $this->qfn = $this->qfn.'&qf'.$k.'='.$this->plain2web($m); $hidden_qfs .= ''."\n"; } } } return $hidden_qfs; } /* }}} */ function web2plain($x) /* {{{ */ { if (isset($x)) { if (is_array($x)) { foreach (array_keys($x) as $key) { $x[$key] = rawurldecode($x[$key]); } } else { $x = rawurldecode($x); } } return $x; } /* }}} */ function plain2web($x) /* {{{ */ { if (isset($x)) { if (is_array($x)) { for ($n=0; $nplain2web($x[$n]); } } else { $x = rawurlencode($x); } } return $x; } /* }}} */ function get_cgi_var($name, $default_value = null) /* {{{ */ { //echo 'get_cgi_var(): requested: '.htmlspecialchars($name).'
'; if (isset($this) && isset($this->cgi['overwrite'][$name])) { return $this->cgi['overwrite'][$name]; } global $HTTP_GET_VARS; $var = $HTTP_GET_VARS[$name]; if (! isset($var)) { global $HTTP_POST_VARS; $var = $HTTP_POST_VARS[$name]; } if (isset($var)) { if (is_array($var)) { foreach (array_keys($var) as $key) { $var[$key] = stripslashes($var[$key]); } } else { $var = stripslashes($var); } } else { $var = $default_value; } if (isset($this) && $var === null && isset($this->cgi['append'][$name])) { return $this->cgi['append'][$name]; } return $var; } /* }}} */ function get_server_var($name) /* {{{ */ { if (isset($_SERVER[$name])) { return $_SERVER[$name]; } global $HTTP_SERVER_VARS; if (isset($HTTP_SERVER_VARS[$name])) { return $HTTP_SERVER_VARS[$name]; } global $name; if (isset($$name)) { return $$name; } return null; } /* }}} */ /* * Debug functions */ function print_get_vars ($miss = 'No GET variables found') // debug only /* {{{ */ { global $HTTP_GET_VARS; // we parse form GET variables if (is_array($HTTP_GET_VARS)) { echo "

Variables per GET "; foreach ($HTTP_GET_VARS as $k => $v) { if (is_array($v)) { foreach ($v as $akey => $aval) { // $HTTP_GET_VARS[$k][$akey] = strip_tags($aval); // $$k[$akey] = strip_tags($aval); echo "$k\[$akey\]=$aval "; } } else { // $HTTP_GET_VARS[$k] = strip_tags($val); // $$k = strip_tags($val); echo "$k=$v "; } } echo '

'; } else { echo '

'; echo $miss; echo '

'; } } /* }}} */ function print_post_vars($miss = 'No POST variables found') // debug only /* {{{ */ { global $HTTP_POST_VARS; // we parse form POST variables if (is_array($HTTP_POST_VARS)) { echo "

Variables per POST "; foreach ($HTTP_POST_VARS as $k => $v) { if (is_array($v)) { foreach ($v as $akey => $aval) { // $HTTP_POST_VARS[$k][$akey] = strip_tags($aval); // $$k[$akey] = strip_tags($aval); echo "$k\[$akey\]=$aval "; } } else { // $HTTP_POST_VARS[$k] = strip_tags($val); // $$k = strip_tags($val); echo "$k=$v "; } } echo '

'; } else { echo '

'; echo $miss; echo '

'; } } /* }}} */ function print_vars ($miss = 'Current instance variables') // debug only /* {{{ */ { echo "$miss "; echo 'page_name='.$this->page_name.' '; echo 'hn='.$this->hn.' '; echo 'un='.$this->un.' '; echo 'pw='.$this->pw.' '; echo 'db='.$this->db.' '; echo 'tb='.$this->tb.' '; echo 'key='.$this->key.' '; echo 'key_type='.$this->key_type.' '; echo 'inc='.$this->inc.' '; echo 'options='.$this->options.' '; echo 'fdd='.$this->fdd.' '; echo 'fl='.$this->fl.' '; echo 'fm='.$this->fm.' '; echo 'sfn='.htmlspecialchars($this->get_sfn_cgi_vars()).' '; echo 'qfn='.$this->qfn.' '; echo 'sw='.$this->sw.' '; echo 'rec='.$this->rec.' '; echo 'prev='.$this->prev.' '; echo 'next='.$this->next.' '; echo 'saveadd='.$this->saveadd.' '; echo 'moreadd='.$this->moreadd.' '; echo 'savechange='.$this->savechange.' '; echo 'morechange='.$this->morechange.' '; echo 'savedelete='.$this->savedelete.' '; echo 'operation='.$this->operation.' '; echo "\n"; } /* }}} */ /* * Display buttons at top and bottom of page - sparky */ function display_list_table_buttons($total_recs) /* {{{ */ { // Are we doing a listall? $listall = $this->inc <= 0; // note that '; echo '' . "\n"; $disabled = ($this->fm > 0 && ! $listall) ? '' : ' disabled'; echo ' '; if ($this->add_enabled ()) { echo ' '; } if ($this->nav_buttons()) { if ($this->view_enabled()) { echo ' '; } if ($this->change_enabled()) { echo ' '; } if ($this->copy_enabled()) { echo ' '; } if ($this->delete_enabled()) { echo ' '; } // if else } $disabled = ($this->fm + $this->inc < $total_recs && ! $listall) ? '' : ' disabled'; echo ''; // Message is now written here echo ''.$this->message.''; // display page and records statistics echo '' . "\n"; if ($listall) { echo $this->labels['Page'].': 1 '.$this->labels['of'].' 1'; } else { echo $this->labels['Page'].': '; echo (($this->fm / $this->inc)+1); echo ' '.$this->labels['of'].' '; echo max(1, ceil($total_recs / abs($this->inc))); } echo '  '.$this->labels['Records'].': '.$total_recs; echo ''."\n"; } /* }}} */ /* * Display buttons at top and bottom of page - sparky */ function display_record_buttons() /* {{{ */ { // TODO: classify this table and cells echo ''; echo ''; echo '
' . "\n"; if ($this->change_operation()) { echo ''."\n"; echo ''."\n"; echo ''."\n"; } elseif ($this->add_operation()) { echo ''."\n"; echo ''."\n"; echo ''."\n"; } elseif ($this->copy_operation()) { echo ''."\n"; echo ''."\n"; } elseif ($this->delete_operation()) { echo ''."\n"; echo ''."\n"; } elseif ($this->view_operation()) { if ($this->change_enabled()) { echo ''."\n"; } echo ''."\n"; } // Message is now written here echo ''.$this->message.'
'."\n"; } /* }}} */ /* * Table Page Listing */ function list_table() /* {{{ */ { if ($this->fm == '') { $this->fm = 0; } if ($this->prev_operation()) { $this->fm = $this->fm - $this->inc; if ($this->fm < 0) { $this->fm = 0; } } if ($this->next_operation()) { $this->fm += $this->inc; } /* * If user is allowed to Change/Delete records, we need an extra column * to allow users to select a record */ $select_recs = $this->key != '' && ($this->change_enabled() || $this->delete_enabled() || $this->view_enabled()); // Are we doing a listall? $listall = $this->inc <= 0; /* * Display the MySQL table in an HTML table */ $comp_ops = array( ''=>'','%3C'=>'%3C','%3C%3D'=>'%3C%3D', '%3D'=>'%3D','%3E%3D'=>'%3E%3D','%3E'=>'%3E'); echo ''."\n"; $this->write_origvars_html($this->get_sfn_cgi_vars()); echo ''."\n"; $prev_qfn = $this->qfn; $hidden_qfs = $this->get_qf_hidden_fields(); // if sort sequence has changed, restart listing $this->qfn != $prev_qfn && $this->fm = 0; if (0) { // TODO: delete me! echo '$this->qfn vs. $prev_qfn comparsion:::::'; echo ''.htmlspecialchars($this->qfn).':::::'; echo ''.htmlspecialchars($prev_qfn).':::::
'; echo 'comparsion '.($this->qfn == $prev_qfn ? 'proved' : 'failed').''; echo '
'; } // Display buttons at top and/or bottom of page. // Setup query to get num_rows. (sparky) $total_recs = 0; $count_parts = array( 'type' => 'select', 'select' => 'count(*) as num_rows', 'from' => $this->create_join_clause(), 'where' => $this->make_where_from_query_opts()); $res = $this->myquery($this->query_make($count_parts), __LINE__); $row = @mysql_fetch_array($res, MYSQL_ASSOC); $total_recs = $row['num_rows']; if ($this->nav_up()) { $this->display_list_table_buttons($total_recs); echo '
'."\n"; } if ($this->cgi['persist'] != '') { $this->write_origvars_html($this->cgi['persist']); } if (!$this->fl) { echo($hidden_qfs); } echo ''."\n"; echo ''."\n"; echo ''."\n"; echo ''."\n"; /* * System (navigation, selection) columns counting */ $sys_cols = 0; $sys_cols += intval($this->filter_enabled() || $select_recs); if ($sys_cols > 0) { $sys_cols += intval($this->nav_buttons() && ($this->nav_text_links() || $this->nav_graphic_links())); } /* * We need an initial column(s) (sys columns) * if we have filters, Changes or Deletes enabled */ if ($sys_cols) { echo ''."\n"; } for ($k = 0; $k < $this->num_fds; $k++) { $fd = $this->fds[$k]; if ($this->displayed[$k]) { $fdn = $this->fdd[$fd]['name']; $w = isset($this->fdd[$fd]['width']) ? ' width="'.$this->fdd[$fd]['width'].'"' : ''; if (! $this->fdd[$fd]['sort'] || $this->hidden($fd) || $this->password($fd)) { echo ''.$fdn.''."\n"; } else { // Clicking on the current sort field reverses the sort order $new_sfn = $this->sfn; array_unshift($new_sfn, in_array("$k", $new_sfn, 1) ? "-$k" : $k); echo ''.$fdn.''."\n"; } } // if we have any aggregates going on, then we have to list all results $var_to_total = 'qf'.$k.'_aggr'; $$var_to_total = $this->get_cgi_var($var_to_total); if ($$var_to_total != '') { $listall = true; } } // for echo ''."\n"; /* * Prepare the SQL Query from the data definition file */ $qparts['type'] = 'select'; $qparts['select'] = $this->create_column_list(); // Even if the key field isn't displayed, we still need its value if ($select_recs) { if (!in_array ($this->key, $this->fds)) { $qparts['select'] .= ','.$this->fqn($this->key); } } $qparts['from'] = $this->create_join_clause(); $qparts['where'] = $this->make_where_from_query_opts(); // build up the ORDER BY clause if (isset($this->sfn)) { // WTF $raw_sort_fields? //$raw_sort_fields = array(); $sort_fields = array(); $sort_fields_w = array(); foreach ($this->sfn as $field) { if ($field[0] == '-') { $field = substr($field, 1); $desc = true; } else { $field = $field; $desc = false; } //$raw_sort_field = 'qf'.$field; $sort_field = $this->fqn($field); $sort_field_w = $this->fdd[$field]['name']; $this->fdd[$field]['expression'] && $sort_field_w .= ' (expression)'; if ($desc) { $sort_field .= ' DESC'; $sort_field_w .= ' '.$this->labels['descending']; } else { $sort_field_w .= ' '.$this->labels['ascending']; } //$raw_sort_fields[] = $raw_sort_field; $sort_fields[] = $sort_field; $sort_fields_w[] = $sort_field_w; } if (count($sort_fields) > 0) { $qparts['orderby'] = join(',', $sort_fields); } } $to = $this->fm + $this->inc; if ($listall) { $qparts['limit'] = $this->fm.',-1'; } else { $qparts['limit'] = $this->fm.','.$this->inc; } /* * Main list_table() query * * Each row of the HTML table is one record from the SQL query. We must * perform this query before filter printing, because we want to use * mysql_field_len() function. We will also fetch the first row to get * the field names. */ $res = $this->myquery($this->query_make($qparts), __LINE__); $row = @mysql_fetch_array($res, MYSQL_ASSOC); /* * FILTER * * Draw the filter and fill it with any data typed in last pass and stored * in the array parameter keyword 'filter'. Prepare the SQL WHERE clause. */ if ($row !== false && $this->fl) { echo ''; echo ''."\n"; /* Variable $fields is used to get index of particular field in result. That index can be passed in example to mysql_field_len() function. Use field names as indexes to $fields array. */ $fields = array_flip(array_keys($row)); for ($k = 0; $k < $this->num_fds; $k++) { $this->field_name = $this->fds[$k]; $fd = $this->field_name; $this->field = $this->fdd[$fd]; $l = 'qf'.$k; $lc = 'qf'.$k.'_comp'; $$l = $this->get_cgi_var($l); $$lc = $this->get_cgi_var($lc); $m = $this->web2plain($$l); // get the field name and value $mc = $this->web2plain($$lc); // get the comparison operator for numeric/date types $widthStyle = ''; if (isset($this->fdd[$fd]['width'])) { $widthStyle = ' STYLE=\'width: "'.(6*$this->fdd[$fd]['width']).'px"\''; } $opened = false; if ($this->displayed[$k]) { echo ''; $opened = true; } $type = $this->fdd[$fd]['type']; if ($this->col_has_values($k)) { $type = 'string'; } /* if ( stristr($this->fdd[$fd]['options'],'L') or !isset ($this->fdd[$fd]['options'])) */ if (! $this->displayed[$k]) { continue; } if ($this->fdd[$fd]['select'] == 'D' or $this->fdd[$fd]['select'] == 'M') { /* * Multiple fields processing - default size is 2 and array required for values */ $multiple = $this->fdd[$fd]['select'] == 'M'; $selected = $m; $x = isset($this->fdd[$k]['values']['table']) || !$this->col_has_values($k) ? $this->set_values_from_table($k, array('*' => '*')) : array('*' => '*') + (array) $this->fdd[$k]['values2'] + (array) $this->fdd[$k]['values']; echo $this->htmlSelect($l, $x, $selected, $multiple); } elseif ($this->fdd[$fd]['select'] == 'T') { // this is where we put the comparison selects if (! $this->password($k) && ! $this->hidden($k)) { $size_ml_props = ''; if ($type != 'blob') { $maxlen = intval($this->fdd[$k]['maxlen']); $maxlen > 0 || $maxlen = intval(@mysql_field_len($res, $fields["qf$k"])); $size = $maxlen < 30 ? min($maxlen, 8) : 12; $size && $size_ml_props .= ' size="'.$size.'"'; $maxlen && $size_ml_props .= ' maxlength="'.$maxlen.'"'; if (0) { echo $this->fdd[$fd]['name'],'|qf',$k,'|'; echo mysql_field_len($res, $fields["qf$k"]); echo "|size=$size|maxlen=$maxlen
\n"; } } if ($this->col_is_string($k)) { // it's treated as a string echo ''; } elseif ($this->col_is_date($k)) { // it's a date //echo $this->htmlSelect($l.'_comp',$comp_ops,$$lc); // first get any date elements that were passed in //$filter_val = $this->gather_search_date_fields_into_mysql_timestamp('qf'.$k); // display the search formlet //if ($mc) { // //echo $this->display_search_field_date($type,'qf'.$k,$filter_val,$this->fdd[$k]['datemask']); // //echo $this->mdate_displayForm($filter_val,$type,'qf'.$k,$this->fdd[$k]['datemask'],true); // echo $this->mdate_disperse($k,true,$filter_val); //} //else { // //echo $this->display_search_field_date( $type,'qf'.$k,'',$this->fdd[$k]['datemask']); // echo $this->mdate_displayForm('',$type,'qf'.$k,$this->fdd[$k]['datemask'],true); //} // it's treated as a string echo ''; } elseif ($this->col_is_number($k)) { // it's a number echo $this->htmlSelect($l.'_comp',$comp_ops,$$lc); // it's treated as a string echo ''; } else { // type is 'unknown' or not set, it's treated as a string echo ''; } } else { echo ' '; } // if it's int or real and if not password or hidden, display aggr options /* XXX Disabled until we have time to work on this if ((! $this->password($k) && ! $this->hidden($k)) && (($this->col_is_number($k)) && (! isset($this->fdd[$k]['values'])))) { $var_to_total = 'qf'.$k.'_aggr'; global $$var_to_total; $aggr_function = $$var_to_total; if (isset($$var_to_total)) { $vars_to_total[] = $this->fqn($k); $aggr_from_clause .= ' '.$aggr_function.'('. $this->fqn($k). ') as '.$var_to_total; } echo '
Aggr: '; echo $this->htmlSelect($var_to_total,$this->sql_aggrs,$$var_to_total); if ($$var_to_total != '') { $listall = true; } } else { echo ' '; } */ echo ''."\n"; } else { echo '
'."\n"; } // if elseif else } // for echo ''."\n"; } /* * Display sorting sequence */ if ($qparts['orderby'] && $this->display['sort']) { $cgi_persist = $this->cgi['persist']; $cgi_persist != '' && $cgi_persist[0] = '?'; echo ''; echo ''."\n"; } /* * Display the current query */ $text_query = $this->make_text_where_from_query_opts(); if ($text_query != '' && $this->display['query']) { echo ''; echo ''."\n"; } if ($this->nav_text_links() || $this->nav_graphic_links()) { // gather query & GET options to preserve for Update/Delete links $qstrparts = array(); if (count($this->qo) > 0) { foreach ($this->qo as $key=>$val) { if ($key != '' && $key != 'operation' && ! is_array($val)) $qstrparts[] = "$key=$val"; } } if (count($this->get_opts) > 0) { foreach ($this->get_opts as $key=>$val) { if ($key != '' && $key != 'operation' && ! is_array($val)) $qstrparts[] = "$key=$val"; } } // preserve sort field number, filter row, and first record to display isset($this->sfn) && $qstrparts[] = $this->get_sfn_cgi_vars(); isset($this->fl) && $qstrparts[] = 'fl='.$this->fl; isset($this->fm) && $qstrparts[] = 'fm='.$this->fm; // do we need to preserve filter (filter query) and sw (filter display/hide button)? $qpview = $qstrparts; $qpview[] = 'operation='.$this->labels['View']; $qpviewStr = '?'.join('&',$qpview).$this->qfn; $qpcopy = $qstrparts; $qpcopy[] = 'operation='.$this->labels['Copy']; $qpcopyStr = '?'.join('&',$qpcopy).$this->qfn; $qpchange = $qstrparts; $qpchange[] = 'operation='.$this->labels['Change']; $qpchangeStr = '?'.join('&',$qpchange).$this->qfn; $qpdelete = $qstrparts; $qpdelete[] = 'operation='.$this->labels['Delete']; $qpdeleteStr = '?'.join('&',$qpdelete).$this->qfn; } $fetched = true; $first = true; $rowCount = 0; while ((!$fetched && ($row = @mysql_fetch_array($res, MYSQL_ASSOC)) !== false) || ($fetched && $row !== false)) { $fetched = false; echo '\n"; if ($sys_cols) { $key_rec = $row['qf'.$this->key_num]; $qviewStr = $qpviewStr .'&rec='.$key_rec.$this->cgi['persist']; $qcopyStr = $qpcopyStr .'&rec='.$key_rec.$this->cgi['persist']; $qchangeStr = $qpchangeStr.'&rec='.$key_rec.$this->cgi['persist']; $qdeleteStr = $qpdeleteStr.'&rec='.$key_rec.$this->cgi['persist']; if ($select_recs) { if (! $this->nav_buttons() || $sys_cols > 1) { echo ''."\n"; } if ($this->nav_buttons()) { echo ''."\n"; } } elseif ($this->filter_enabled()) { echo ''."\n"; } } // Calculate the url query string for optional URL support $urlqueryproto = 'fm='.$this->fm .'&sfn='.$this->get_sfn_cgi_vars() .'&fl='.$this->fl .'&qfn='.$this->qfn; for ($k = 0; $k < $this->num_fds; $k++) { $fd = $this->fds[$k]; if (! $this->displayed[$k]) { continue; } if ($this->hidden($k) || $this->password($k)) { echo ''."\n"; continue; } // XXX: echo 'displayed: '.$k.'-'.$fd; /* TODO: what's this?! if ((trim($row[$k]) == '') or ($row[$k] == 'NULL')) { echo ''."\n"; } else { */ // display the contents $colattrs = $this->fdd[$fd]['colattrs']; if ($colattrs != '') $colattrs = ' '.$colattrs; if ($this->fdd[$fd]['nowrap']) $colattrs .= ' nowrap'; if (isset($this->fdd[$fd]['width'])) { $colattrs .= ' width="'.$this->fdd[$fd]['width'].'"'; } echo ''; // displayable if (isset($this->fdd[$k]['URL']) || isset($this->fdd[$k]['URLprefix']) || isset($this->fdd[$k]['URLpostfix'])) { /* It's an URL Put some conveniences in the namespace for the user to be able to use in the URL string. */ $key = $key_rec; $name = $this->fds[$k]; $value = $row["qf$k"]; $page = $this->page_name; $urlstr = $urlqueryproto.'&rec='.$key.$this->cgi['persist']; $urllink = isset($this->fdd[$k]['URL']) ? eval('return "'.$this->fdd[$k]['URL'].'";') : $value; $urldisp = isset($this->fdd[$k]['URLdisp']) ? eval('return "'.$this->fdd[$k]['URLdisp'].'";') : $value; $target = isset($this->fdd[$k]['URLtarget']) ? 'target="'.htmlspecialchars($this->fdd[$k]['URLtarget']).'" ' : ''; isset($this->fdd[$k]['URLprefix']) && $urllink = $this->fdd[$k]['URLprefix'].$urllink; isset($this->fdd[$k]['URLpostfix']) && $urllink .= $this->fdd[$k]['URLpostfix']; if (strlen($urllink) <= 0 || strlen($urldisp) <= 0) { echo ' '; } else { $urllink = htmlspecialchars($urllink); $urldisp = htmlspecialchars($urldisp); echo ''.$urldisp.''; } } elseif (isset($this->fdd[$k]['datemask'])) { // display date according to a mask if any //echo $this->mdate_set($row[$k],$this->fdd[$k]['type'],$this->fdd[$k]['datemask']); //echo // $this->mdate_displayPlain( // $this->mdate_from_mysql( // $row[$k]), // ( // $this->fdd[$k]['datemask']? // $this->fdd[$k]['datemask'] // : // $this->mdate_masks[$this->fdd[$k]['type']] // ) // ); //echo $row[$k]; // it's a normal field $shortdisp = $row["qf$k"]; if ($this->fdd[$k]['strip_tags']) { $shortdisp = strip_tags($shortdisp); } if (isset($this->fdd[$k]['trimlen']) && strlen($shortdisp) > $this->fdd[$k]['trimlen']) { $shortdisp = ereg_replace("[\r\n\t ]+", ' ', $shortdisp); $shortdisp = substr($shortdisp,0,$this->fdd[$k]['trimlen']-3).'...'; } echo nl2br($this->htmlDisplay($this->fdd[$k], $shortdisp)); } else { // it's a normal field if ($this->is_values2($k, $row["qf$k"])) { $escape_flag = false; $shortdisp = $this->fdd[$k]['values2'][$row['qf'.$k.'_idx']]; } else { $escape_flag = true; $shortdisp = $row["qf$k"]; if ($this->fdd[$k]['strip_tags']) { $shortdisp = strip_tags($shortdisp); } if (isset($this->fdd[$k]['trimlen']) && strlen($shortdisp) > $this->fdd[$k]['trimlen']) { $shortdisp = ereg_replace("[\r\n\t ]+",' ',$shortdisp); $shortdisp = substr($shortdisp,0,$this->fdd[$k]['trimlen']-3).'...'; } } echo nl2br($this->htmlDisplay($this->fdd[$k], $shortdisp, true, true, true, $escape_flag)); } echo ''."\n"; } // for echo ''."\n"; } // while /* * Display and accumulate column aggregation info, do totalling query * XXX this feature does not work yet!!! */ // aggregates listing (if any) if ($$var_to_total) { // do the aggregate query if necessary //if ($vars_to_total) { $qp = array(); $qp['type'] = 'select'; $qp['select'] = $aggr_from_clause; $qp['from'] = $this->create_join_clause (); $qp['where'] = $this->make_where_from_query_opts(); $tot_query = $this->query_make($qp); //$this->elog('TOT_QRY: '.$tot_query,__LINE__); $totals_result = $this->myquery($tot_query,__LINE__); $tot_row = @mysql_fetch_array($totals_result, MYSQL_ASSOC); //} $qp_aggr = $qp; echo "\n".''."\n".''."\n"; /* echo ''; echo ''; */ // display the results for ($k=0;$k<$this->num_fds;$k++) { $fd = $this->fds[$k]; if (stristr($this->fdd[$fd]['options'],'L') or !isset($this->fdd[$fd]['options'])) { echo ''."\n"; } } echo ''."\n"; } echo '
'; if ($this->filter_enabled()) { if ($this->fl) { echo ''; echo ''; } else { echo ''; } } else { echo ' '; } echo '
'; echo ' 
' .'' .$this->labels['Clear'].'' .$this->labels['Sorted By'].': ' .join(', ', $sort_fields_w).'
' .''.$this->labels['Clear'].'' .$this->labels['Current Query'].': ' .htmlspecialchars($text_query).'
'; } if ($this->nav_graphic_links()) { $printed_out = false; if ($this->view_enabled()) { $printed_out = true; echo ''
								.htmlspecialchars($this->labels['View']).''; } if ($this->change_enabled()) { $printed_out && print(' '); $printed_out = true; echo ''
								.htmlspecialchars($this->labels['Change']).''; } if ($this->copy_enabled()) { $printed_out && print(' '); $printed_out = true; echo ''
								.htmlspecialchars($this->labels['Copy']).''; } if ($this->delete_enabled()) { $printed_out && print(' '); $printed_out = true; echo ''
								.htmlspecialchars($this->labels['Delete']).''; } } if ($this->nav_text_links()) { if ($this->nav_graphic_links()) { echo '
'; } $printed_out = false; if ($this->view_enabled()) { $printed_out = true; echo 'V '; } if ($this->change_enabled()) { $printed_out && print(' '); $printed_out = true; echo 'C '; } if ($this->copy_enabled()) { $printed_out && print(' '); $printed_out = true; echo 'P '; } if ($this->delete_enabled()) { $printed_out && print(' '); $printed_out = true; echo 'D'; } } if (! $this->nav_buttons() || $sys_cols > 1) { echo '
'; echo ' '.$this->labels['hidden'].' 
 '; echo printarray($qp_aggr); echo printarray($vars_to_total); echo ''.$var_to_total.' '.$$var_to_total.''; $aggr_var = 'qf'.$k.'_aggr'; $$aggr_var = $this->get_cgi_var($aggr_var); if ($$aggr_var) { echo $this->sql_aggrs[$$aggr_var].': '.$tot_row[$aggr_var]; } else { echo ' '; } echo '
'."\n"; // end of table rows listing if ($this->nav_down()) { echo '
'."\n"; $this->display_list_table_buttons($total_recs); } echo ''."\n"; //phpinfo(); /* foreach ( array( // '1999-12-31'=>'%Y-%m-%d', // '99-Mar-31'=>'%y-%M-%d', // '99-1-31'=>'%y-%n-%d' // 'March 8, 1999'=>'%F %j, %Y' // 'March 8, 1999 09:17:32'=>'%F %j, %Y %H:%i:%s' 'March 8, 1999 9:17:32'=>'%F %j, %Y %G:%i:%s' ) as $val=>$mask ) { echo "
\n"; debug_var('val,mask',"$val::$mask"); debug_var('mdate_parse',date('Y m d H:i:s',$this->mdate_parse($val,$mask))); } */ } /* }}} */ function display_record() /* {{{ */ { $this->create_javascripts(); if ($this->cgi['persist'] != '') { $this->write_origvars_html($this->cgi['persist']); } echo ''."\n"; echo ''."\n"; $this->write_origvars_html($this->get_sfn_cgi_vars()); echo ''."\n"; echo $this->get_qf_hidden_fields(); echo ''."\n"; if ($this->nav_up()) { $this->display_record_buttons(); echo '
'."\n"; } echo ''."\n"; if ($this->add_operation()) { $this->display_add_record(); } else { $this->display_copy_change_delete_record(); } echo '
'."\n"; if ($this->nav_down()) { echo '
'."\n"; $this->display_record_buttons(); } echo ''."\n"; } /* }}} */ /* * Action functions */ function do_add_record() /* {{{ */ { // Before trigger if (isset($this->triggers['insert']['before'])) { $ret = include($this->triggers['insert']['before']); if ($ret == false) { return false; } } // Preparing queries $query = ''; $key_col_val = ''; for ($k = 0; $k < $this->num_fds; $k++) { if ($this->processed($k)) { $fd = $this->fds[$k]; if ($fd == $this->key) { $key_col_val = addslashes($this->encode($this->fdd[$k],$fn)); } if ($query == '') { $query = 'INSERT INTO '.$this->tb.' ('.$fd; // ) } else { $query .= ','.$fd; } } } $vals = array(); $vals_ori = array(); for ($k = 0; $k < $this->num_fds; $k++) { if ($this->processed($k)) { if ($this->readonly($k)) { $fn = (string) @$this->fdd[$k]['default']; } else { $fn = $this->get_cgi_var($this->fds[$k]); } $vals_ori[$this->fds[$k]] = is_array($fn) ? join(',',$fn) : $fn; $vals[$k] = addslashes($this->encode($this->fdd[$k],$vals_ori[$this->fds[$k]])); $vals[$k] = "'".$vals[$k]."'"; } } // Real query (no additional query in this method) $query .= ') VALUES ('.join(',',$vals).')'; // ) $res = $this->myquery($query, __LINE__); $this->message = @mysql_affected_rows($this->dbh).' '.$this->labels['record added']; if (! $res) { return false; } // Notify list if (@$this->notify['insert'] || @$this->notify['all']) { $this->email_notify(false, $vals_ori); } // Note change in log table if ($this->logtable) { $query = sprintf('INSERT INTO %s' .' (updated, user, host, operation, tab, rowkey, col, oldval, newval)' .' VALUES (NOW(), "%s", "%s", "insert", "%s", "%s", "", "", "%s")', $this->logtable, addslashes($this->get_server_var('REMOTE_USER')), addslashes($this->get_server_var('REMOTE_ADDR')), addslashes($this->tb), addslashes($key_col_val), addslashes(serialize($vals_ori))); $this->myquery($query, __LINE__); } // After trigger if (isset($this->triggers['insert']['after'])) { $ret = include($this->triggers['insert']['after']); if ($ret == false) { return false; } } return false; } /* }}} */ function do_change_record() /* {{{ */ { // Before trigger if (isset($this->triggers['update']['before'])) { $ret = include($this->triggers['update']['before']); if ($ret == false) { return false; } } // Preparing queries $query_real = ''; $query_oldrec = ''; for ($k = 0; $k < $this->num_fds; $k++) { if ($this->processed($k) && !$this->readonly($k)) { $fd = $this->fds[$k]; if ($fd == $this->key) { $key_col_val = addslashes($this->get_cgi_var($fd)); } $fn = $this->get_cgi_var($fd); $newValue = is_array($fn) ? join(',',$fn) : $fn; $newValue = addslashes($this->encode($this->fdd[$k], $newValue)); if ($query_real == '') { $query_real = 'UPDATE '.$this->tb.' SET '.$fd.'=\''.$newValue.'\''; $query_oldrec = 'SELECT '.$fd; } else { $query_real .= ','.$fd.'=\''.$newValue.'\''; $query_oldrec .= ','.$fd; } $newvalues[$this->fds[$k]] = $fn; } } $where_part = " WHERE (".$this->key.'='.$this->key_delim.$this->rec.$this->key_delim.')'; $query_real .= $where_part; $query_oldrec .= ' FROM ' . $this->tb . $where_part; // Additional query (must go before real query) if (@$this->notify['update'] || @$this->notify['all'] || $this->logtable) { $res_old = $this->myquery($query_oldrec, __LINE__); $oldvalues = @mysql_fetch_array($res_old, MYSQL_ASSOC); for ($k = 0; $k < $this->num_fds; $k++) { if ($this->processed($k) && !$this->readonly($k)) { if ($oldvalues[$this->fds[$k]] == $newvalues[$this->fds[$k]]) { // Removing the same values unset($oldvalues[$this->fds[$k]]); unset($newvalues[$this->fds[$k]]); } } } } // Real query $res = $this->myquery($query_real, __LINE__); $this->message = @mysql_affected_rows($this->dbh).' '.$this->labels['record changed']; if (! $res) { echo 'haha'; return false; } // Notify list if (@$this->notify['update'] || @$this->notify['all']) { $this->email_notify($oldvalues, $newvalues); } // Note change in log table if ($this->logtable) { foreach (array_keys($newvalues) as $key) { $qry = sprintf('INSERT INTO %s' .' (updated, user, host, operation, tab, rowkey, col, oldval, newval)' .' VALUES (NOW(), "%s", "%s", "update", "%s", "%s", "%s", "%s", "%s")', $this->logtable, addslashes($this->get_server_var('REMOTE_USER')), addslashes($this->get_server_var('REMOTE_ADDR')), addslashes($this->tb), addslashes($key_col_val), addslashes($key), addslashes($oldvalues[$key]), addslashes($newvalues[$key])); $this->myquery($qry, __LINE__); } } // After trigger if (isset($this->triggers['update']['after'])) { $ret = include($this->triggers['update']['after']); if ($ret == false) { return false; } } return true; } /* }}} */ function do_delete_record() /* {{{ */ { // Before trigger if (isset($this->triggers['delete']['before'])) { $ret = include($this->triggers['delete']['before']); if ($ret == false) { return false; } } // Preparing queries for ($k = 0; $k < $this->num_fds; $k++) { if ($this->processed($k)) { if ($this->fds[$k] == $this->key) { $key_col_val = addslashes($this->encode($this->fdd[$k], $fn)); } } } // Additional query if (@$this->notify['delete'] || @$this->notify['all'] || $this->logtable) { $query = 'SELECT * FROM '.$this->tb.' WHERE ('.$this->key.' = ' .$this->key_delim.$this->rec.$this->key_delim.')'; // ) $res = $this->myquery($query, __LINE__); $oldrow = @mysql_fetch_array($res, MYSQL_ASSOC); } // Real query $query = 'DELETE FROM '.$this->tb.' WHERE ('.$this->key.' = ' .$this->key_delim.$this->rec.$this->key_delim.')'; // ) $res = $this->myquery($query, __LINE__); $this->message = @mysql_affected_rows($this->dbh).' '.$this->labels['record deleted']; if (! $res) { return false; } // Notify list if (@$this->notify['delete'] || @$this->notify['all']) { $this->email_notify($oldrow, false); } // Note change in log table if ($this->logtable) { $query = sprintf('INSERT INTO %s' .' (updated, user, host, operation, tab, rowkey, col, oldval, newval)' .' VALUES (NOW(), "%s", "%s", "delete", "%s", "%s", "%s", "%s", "")', $this->logtable, addslashes($this->get_server_var('REMOTE_USER')), addslashes($this->get_server_var('REMOTE_ADDR')), addslashes($this->tb), addslashes($key_col_val), addslashes($key), addslashes(serialize($oldrow))); $this->myquery($query, __LINE__); } // After trigger if (isset($this->triggers['delete']['after'])) { $ret = include($this->triggers['delete']['after']); if ($ret == false) { return false; } } return true; } /* }}} */ function email_notify($old_vals, $new_vals) /* {{{ */ { if (! function_exists('mail')) { return false; } if ($old_vals != false && $new_vals != false) { $action = 'update'; $subject = 'Record updated in'; $body = 'An item with '.$this->fdd[$this->key]['name'].' = ' .$this->key_delim.$this->rec.$this->key_delim .' was updated in'; $vals = $new_vals; } elseif ($new_vals != false) { $action = 'insert'; $subject = 'Record added to'; $body = 'A new item was added into'; $vals = $new_vals; } elseif ($old_vals != false) { $action = 'delete'; $subject = 'Record deleted from'; $body = 'An item was deleted from'; $vals = $old_vals; } else { return false; } $addr = $this->get_server_var('REMOTE_ADDR'); $user = $this->get_server_var('REMOTE_USER'); $body = 'This notification e-mail is automatically generated by phpMyEdit.'."\n\n".$body; $body .= ' table '.$this->tb.' in MySQL database '.$this->db.' on '.$this->page_name; $body .= ' by '.($user == '' ? 'unknown user' : "user $user").' from '.$addr; $body .= ' at '.date('d/M/Y H:i').' with the following fields:'."\n\n"; $i = 1; foreach ($vals as $k => $text) { $name = isset($this->fdd[$k]['name~']) ? $this->fdd[$k]['name~'] : $this->fdd[$k]['name']; if ($action == 'update') { $body .= sprintf("[%02s] %s (%s)\n WAS: %s\n IS: %s\n", $i, $name, $k, $old_vals[$k], $new_vals[$k]); } else { $body .= sprintf('[%02s] %s (%s): %s'."\n", $i, $name, $k, $text); } $i++; } $body .= "\n--\r\n"; // \r is needed for signature separating $body .= "phpMyEdit - instant MySQL table editor and code generator\n"; $body .= "http://www.platon.sk/projects/phpMyEdit/\n"; $subject = @$this->notify['prefix'].$subject.' '.$this->db.'.'.$this->tb; $wrap_w = intval(@$this->notify['wrap']); $wrap_w > 0 || $wrap_w = 72; $from = (string) @$this->notify['from']; $from != '' || $from = 'webmaster@'.strtolower($this->get_server_var('SERVER_NAME')); $headers = 'From: '.$from."\n".'X-Mailer: PHP/'.phpversion().' (phpMyEdit)'; $body = wordwrap($body, $wrap_w, "\n", 1); $emails = (array) $this->notify[$action] + (array) $this->notify['all']; foreach ($emails as $email) { if (! empty($email)) { mail(trim($email), trim($subject), $body, $headers); } } return true; } /* }}} */ /* * Recreate functions */ function recreate_fdd() /* {{{ */ { // TODO: one level deeper browsing $action_letter = 'L'; // list by default $this->filter_operation() && $action_letter = 'F'; $this->view_operation() && $action_letter = 'V'; $this->delete_operation() && $action_letter = 'D'; $this->add_operation() && $action_letter = 'A'; $this->change_operation() && $action_letter = 'C'; $this->copy_operation() && $action_letter = 'P'; // Restore backups (if exists) foreach (array_keys($this->fdd) as $column) { foreach (array_keys($this->fdd[$column]) as $col_option) { if ($col_option[strlen($col_option) - 1] != '~') continue; $this->fdd[$column][substr($col_option, 0, strlen($col_option) - 1)] = $this->fdd[$column][$col_option]; unset($this->fdd[$column][$col_option]); } } foreach (array_keys($this->fdd) as $column) { foreach (array_keys($this->fdd[$column]) as $col_option) { if (! strchr($col_option, '|')) continue; $col_ar = explode('|', $col_option, 2); if (! stristr($col_ar[1], $action_letter)) continue; // Make field backups $this->fdd[$column][$col_ar[0] .'~'] = $this->fdd[$column][$col_ar[0]]; $this->fdd[$column][$col_option.'~'] = $this->fdd[$column][$col_option]; // Set particular field $this->fdd[$column][$col_ar[0]] = $this->fdd[$column][$col_option]; unset($this->fdd[$column][$col_option]); } } } /* }}} */ function recreate_displayed() /* {{{ */ { $field_num = 0; $num_fields_displayed = 0; $this->fds = array(); $this->displayed = array(); $this->guidance = false; foreach ($this->fdd as $akey => $aval) { if (preg_match('/^\d*$/', $akey)) /* skipping numeric keys */ continue; $this->fds[$field_num] = $akey; /* We must use here displayed() function, because displayed[] array is not created yet. We will simultaneously create that array as well. */ if ($this->displayed[$field_num] = $this->displayed($field_num)) { $num_fields_displayed++; } /* I *really* want to know what does this foreach() do! -- Nepto [17/10/2002] */ if (is_array($aval['values']) && (! $aval['values']['table'])) { $values = array(); foreach ($aval['values'] as $val) { $values[$val] = $val; } $aval['values'] = $values; } $this->fdd[$field_num] = $aval; $aval['help'] && $this->guidance = true; $field_num++; } if (0) { echo 'Displayed array:
';
			var_dump($this->displayed);
			echo '

'; } $this->num_fds = $field_num; $this->num_fields_displayed = $num_fields_displayed; $this->key_num = array_search($this->key, $this->fds); /* Adds first displayed column into sorting fields by replacing last array entry. Also remove duplicite values and change column names to their particular field numbers. Note that entries like [0]=>'9' [1]=>'-9' are correct and they will have desirable sorting behaviour. So there is no need to remove them. */ for ($k = 0; ! $this->displayed[$k]; $k++); $this->sfn[count($this->sfn) - 1] = "$k"; // important quotes $this->sfn = array_unique($this->sfn); $check_ar = array(); foreach ($this->sfn as $key => $val) { if (preg_match('/^[-]?\d*$/', $val)) { // skipping numeric keys $val = abs($val); if (in_array($val, $check_ar) || $this->hidden($val) || $this->password($val)) { unset($this->sfn[$key]); } else { $check_ar[] = $val; } continue; } if ($val[0] == '-') { $val = substr($val, 1); $minus = '-'; } else { $minus = ''; } if (($val = array_search($val, $this->fds)) === false || $this->hidden($val) || $this->password($val)) { unset($this->sfn[$key]); } else { $val = intval($val); if (in_array($val, $check_ar)) { unset($this->sfn[$key]); } else { $this->sfn[$key] = $minus.$val; $check_ar[] = $val; } } } $this->sfn = array_unique($this->sfn); return true; } /* }}} */ /* * Error handling function */ function error($message) /* {{{ */ { echo '

phpMyEdit error: '.htmlspecialchars($message).'

'."\n"; return false; } /* }}} */ /* * Database connection function */ function connect() /* {{{ */ { if (!isset($this->db)) { $this->error('no database defined'); return false; } if (!isset ($this->tb)) { $this->error('no table defined'); return false; } if ($this->dbh = @mysql_pconnect($this->hn, $this->un, $this->pw)) ; else { $this->error('could not connect to MySQL'); return false; } return true; } /* }}} */ /* * Database disconnection function */ function disconnect() /* {{{ */ { @mysql_close($this->dbh); } /* }}} */ /* * The workhorse */ function execute() /* {{{ */ { // DEBUG - uncomment to enable /* //phpinfo(); $this->print_get_vars(); $this->print_post_vars(); $this->print_vars(); echo "
query opts:\n";
		echo print_r($this->query_opts);
		echo "
\n"; echo "
get vars:\n";
		echo print_r($this->get_opts);
		echo "
\n"; */ // Let's do explicit quoting - it's safer set_magic_quotes_runtime(0); // Checking if language file inclusion was successful if (! is_array($this->labels)) { $this->error('could not locate language files'); return false; } // Database connection if ($this->connect() == false) { return false; } /* * ====================================================================== * Pass 3: process any updates generated if the user has selected * a save button during Pass 2 * ====================================================================== */ if ($this->saveadd == $this->labels['Save']) { $this->do_add_record(); } if ($this->moreadd == $this->labels['More']) { $this->do_add_record(); $this->operation = $this->labels['Add']; // to force add operation $this->recreate_fdd(); $this->recreate_displayed(); } if ($this->savechange == $this->labels['Save']) { $this->do_change_record(); } if ($this->morechange == $this->labels['Apply']) { $this->do_change_record(); $this->operation = $this->labels['Change']; // to force change operation $this->recreate_fdd(); $this->recreate_displayed(); } if ($this->savedelete == $this->labels['Delete']) { $this->do_delete_record(); } /* * ====================================================================== * Pass 2: display an input/edit/confirmation screen if the user has * selected an editing button on Pass 1 through this page * ====================================================================== */ if ($this->add_operation() || $this->change_operation() || $this->delete_operation() || $this->view_operation() || $this->copy_operation()) { $this->display_record(); } /* * ====================================================================== * Pass 1 and Pass 3: display the MySQL table in a scrolling window on * the screen (skip this step in 'Add More' mode) * ====================================================================== */ else { $this->list_table(); } $this->disconnect(); global $phpMyEdit_timer; if ($this->display['time'] && $phpMyEdit_timer) { echo $phpMyEdit_timer->end(); } } /* }}} */ /* * Class constructor */ function phpMyEdit($opts) /* {{{ */ { /* * Creating directory variables */ $this->dir['root'] = dirname(__FILE__) . (strlen(dirname(__FILE__)) > 0 ? '/' : ''); $this->dir['lang'] = $this->dir['root'].'lang/'; /* * Creting URL variables */ $this->url['images'] = 'images/'; isset($opts['url']['images']) && $this->url['images'] = $opts['url']['images']; /* * Instance class variables */ $this->hn = $opts['hn']; $this->hn = $opts['hn']; $this->un = $opts['un']; $this->pw = $opts['pw']; $this->db = $opts['db']; $this->tb = $opts['tb']; $this->key = $opts['key']; $this->key_type = $opts['key_type']; $this->inc = $opts['inc']; $this->options = $opts['options']; $this->fdd = $opts['fdd']; $this->multiple = intval($opts['multiple']); $this->multiple <= 0 && $this->multiple = 2; $this->display = @$opts['display']; $this->filters = @$opts['filters']; $this->triggers = @$opts['triggers']; $this->notify = @$opts['notify']; $this->logtable = @$opts['logtable']; $this->page_name = $this->tb; $opts['page_name'] && $this->page_name = $opts['page_name']; // alternate row background colors /* What's this?! if (isset($opts['bgcolorOdd'])) { $this->bgcolorOdd = 'White'; } else { $this->bgcolorOdd = $opts['bgcolorOdd']; } if (isset($opts['bgColorEven'])) { $this->bgcolorEven = 'Silver'; } else { $this->bgcolorEven = $opts['bgcolorEven']; } */ // navigation $this->navigation = @$opts['navigation']; if (! $this->nav_buttons() && ! $this->nav_text_links() && ! $this->nav_graphic_links()) { $this->navigation .= 'B'; // buttons are default } if (! $this->nav_up() && ! $this->nav_down()) { $this->navigation .= 'D'; // down position is default } // language labels (must go after navigation) $this->labels = $this->make_language_labels($opts['language'] ? $opts['language'] : $this->get_server_var('HTTP_ACCEPT_LANGUAGE')); // CGI variables $this->cgi['append'] = $opts['cgi']['append']; $this->cgi['overwrite'] = $opts['cgi']['overwrite']; $this->cgi['persist'] = ''; if (@is_array($opts['cgi']['persist'])) { foreach ($opts['cgi']['persist'] as $key => $val) { $this->cgi['persist'] .= '&'.urlencode($key).'='.urlencode($val); } } /* * Find the URL to post forms */ $this->page_name = basename($this->get_server_var('PHP_SELF')); /* * Sorting variables */ $this->sfn = $this->get_cgi_var('sfn'); isset($this->sfn) || $this->sfn = array(); is_array($this->sfn) || $this->sfn = array($this->sfn); isset($opts['sort_field']) || $opts['sort_field'] = array(); is_array($opts['sort_field']) || $opts['sort_field'] = array($opts['sort_field']); $this->sfn = array_merge($this->sfn, $opts['sort_field']); $this->sfn[] = '0'; // this last entry will be replaced in recreate_displayed() /* * Form variables all around */ $this->operation = $this->get_cgi_var('operation'); $this->apply = $this->get_cgi_var('apply'); $this->fl = intval($this->get_cgi_var('fl')); $this->fm = intval($this->get_cgi_var('fm')); $this->qfn = $this->get_cgi_var('qfn'); $this->sw = $this->get_cgi_var('sw'); $this->rec = $this->get_cgi_var('rec', ''); // Fixed #523390 [7/8/2002] [2/2] $this->prev = $this->get_cgi_var('prev'); $this->next = $this->get_cgi_var('next'); $this->saveadd = $this->get_cgi_var('saveadd'); $this->moreadd = $this->get_cgi_var('moreadd'); $this->savechange = $this->get_cgi_var('savechange'); $this->morechange = $this->get_cgi_var('morechange'); $this->savedelete = $this->get_cgi_var('savedelete'); /* * Filter setting */ if (isset($this->sw)) { $this->sw == $this->labels['Search'] && $this->fl = 1; $this->sw == $this->labels['Hide'] && $this->fl = 0; $this->sw == $this->labels['Clear'] && $this->fl = 0; } /* * Specific $fdd modifications depending on performed action */ $this->recreate_fdd(); /* * Extract SQL Field Names and number of fields */ $this->recreate_displayed(); /* * Clear action */ if ($this->sw == $this->labels['Clear']) { for ($k = 0; $k < $this->num_fds; $k++) { $this->cgi['overwrite']["qf$k"] = ''; $this->cgi['overwrite']["qf$k".'_comp'] = ''; } } /* * Constants */ // code to use this is commented out $this->sql_aggrs = array( '' => '', 'sum' => 'Total', 'avg' => 'Average', 'min' => 'Minimum', 'max' => 'Maximum', 'count' => 'Count'); // to support quick type checking $this->stringTypes = array('string','blob','set','enum'); $this->numberTypes = array('int','real'); $this->dateTypes = array('date','datetime','timestamp','time','year'); // mdate constants $this->mdate_masks = array( 'date'=>'%Y-%m-%d', 'datetime'=>'%Y-%m-%d %H:%i:%s', 'timestamp'=>'%Y%m%d%H%i%s', 'time'=>'%H:%i:%s', 'year'=>'%Y'); $this->mdate_daterange = range(date('Y')-10,date('Y')+10); $this->months_short = array( '~~PME~~'=>0, 'Jan'=>1, 'Feb'=>2, 'Mar'=>3, 'Apr'=>4, 'May'=>5, 'Jun'=>6, 'Jul'=>7, 'Aug'=>8, 'Sep'=>9, 'Oct'=>10, 'Nov'=>11, 'Dec'=>12); $this->months_long = array( '~~PME~~'=>0, 'January'=>1,'February'=>2,'March'=>3, 'April'=>4,'May'=>5,'June'=>6, 'July'=>7,'August'=>8,'September'=>9, 'October'=>10,'November'=>11,'December'=>12); $this->months_long_keys = array_keys($this->months_long); /* If you are phpMyEdit developer, set this to 1. You can also hide some new unfinished and/or untested features under if ($this->development) { new_feature(); } statement. Also note, that this is currently unused. */ $this->development = 0; /* * Preparing some others values * (this was moved from execute() method) */ // Setting key_delim according to key_type if ($this->key_type == 'real') { /* If 'real' key_type does not work, try change MySQL datatype from float to double */ $this->rec = doubleval($this->rec); $this->key_delim = ''; } elseif ($this->key_type == 'int') { $this->rec = intval($this->rec); $this->key_delim = ''; } else { // XXX fix this to use col_is_[type] // if (in_array($this->key_type, // array('string','blob','date','time','datetime','timestamp','year'))) $this->key_delim = '"'; // $this->rec remains unmodified } $this->gather_query_opts(); $this->gather_get_vars(); $this->gather_post_vars(); $this->unify_opts(); // Call to Action // Moved this from the setup.php generated file to here !isset($opts['execute']) && $opts['execute'] = 1; $opts['execute'] && $this->execute(); } /* }}} */ } // end of phpMyEdit class /* Modeline for ViM {{{ * vim:set ts=4: * vim600:fdm=marker fdl=0 fdc=0: * }}} */ ?>