--- phpMyEdit.class.php 2003-08-18 22:31:58.000000000 +0200 +++ phpMyEdit.class.new.php 2003-10-07 11:37:22.789106400 +0200 @@ -168,6 +168,8 @@ { return $this->fdd[$k]['select'] == 'M' && ! $this->fdd[$k]['values']['table']; } function col_has_datemask($k) { return isset($this->fdd[$k]['datemask']) || isset($this->fdd[$k]['strftimemask']); } + function col_has_sqlw($k) { return !$this->virtual($k) && isset($this->fdd[$k]['sqlw']); } + function col_has_sql($k) { return isset($this->fdd[$k]['sql']); } /* * functions for indicating whether navigation style is enabled @@ -193,7 +195,8 @@ function tabs_enabled() { return $this->display['tabs'] && count($this->tabs) > 0; } 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'); } + function virtual($k) { return @$this->fdd[$k]['virtual'] && $this->col_has_sql($k); } + function readonly($k) { return stristr($this->fdd[$k]['options'],'R') || $this->virtual($k) || ($this->col_has_sqlw($k) && !stristr($this->fdd[$k]['sqlw'], '$val') ); } function add_operation() { return $this->operation == $this->labels['Add'] && $this->add_enabled(); } function change_operation() { return $this->operation == $this->labels['Change'] && $this->change_enabled(); } @@ -213,6 +216,9 @@ function processed($k) /* {{{ */ { + if ($this->virtual($k)) { + return false; + } $options = @$this->fdd[$k]['options']; if (! isset($options)) { return true; @@ -223,7 +229,8 @@ ($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')); + ($this->savedelete == $this->labels['Save'] && stristr($options, 'D')) || + $this->col_has_sqlw($k); } /* }}} */ function displayed($k) /* {{{ */ @@ -339,7 +346,7 @@ $desc = &$this->fdd[$field_num]['values']['description']; $qparts['type'] = 'select'; if ($table) { - $qparts['select'] = 'DISTINCT '.$key; + $qparts['select'] = 'DISTINCT '.$table.'.'.$key; if ($desc && is_array($desc) && is_array($desc['columns'])) { $qparts['select'] .= ',CONCAT('; // ) $num_cols = sizeof($desc['columns']); @@ -362,20 +369,29 @@ } else if ($desc && is_array($desc)) { // TODO } else if ($desc) { - $qparts['select'] .= ','.$desc; + $qparts['select'] .= ','.$table.'.'.$desc; $qparts['orderby'] = $desc; } else if ($key) { $qparts['orderby'] = $key; } //$qparts['from'] = "$db.$table.$sel; $qparts['from'] = "$db.$table"; + if (isset($this->fdd[$field_num]['values']['left join'])) { + $qparts['from'] .= ' LEFT JOIN '.$this->fdd[$field_num]['values']['left join']; + } $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; + if ($this->virtual($field_num)) { + $key = $this->fqn($field_num); + } else { + $key = &$this->fds[$field_num]; + } + $qparts['select'] = 'DISTINCT '.$key.' AS PME_KEY'; + $qparts['orderby'] = 'PME_KEY'; + $qparts['from'] = $db.'.'.$this->tb; } $values = array(); $res = $this->myquery($this->query_make($qparts), __LINE__); @@ -389,13 +405,13 @@ { is_numeric($field) || $field = array_search($field, $this->fds); // if read SQL expression exists use it - if (isset($this->fdd[$field]['sql'])) - return $this->fdd[$field]['sql']; + if ($this->col_has_sql($field)) + return $this->print_sql_sqlw_string($this->fdd[$this->fds[$field]]['sql'], true); // on copy/change always use simple key retrieving if ($this->add_operation() || $this->copy_operation() || $this->change_operation()) { - $ret = 'PMEtable0.'.$this->fds[$field]; + $ret = $this->alias['tb'].'.'.$this->fds[$field]; } else { if ($this->fdd[$this->fds[$field]]['values']['description'] && ! $dont_desc) { $desc = &$this->fdd[$this->fds[$field]]['values']['description']; @@ -424,7 +440,7 @@ } elseif (0 && $this->fdd[$this->fds[$field]]['values']['column'] && ! $dont_cols) { $ret = 'PMEjoin'.$field.'.'.$this->fdd[$this->fds[$field]]['values']['column']; } else { - $ret = 'PMEtable0.'.$this->fds[$field]; + $ret = $this->alias['tb'].'.'.$this->fds[$field]; } // TODO: not neccessary, remove me! if (is_array($this->fdd[$this->fds[$field]]['values2'])) { @@ -437,7 +453,9 @@ { $fields = array(); for ($k = 0; $k < $this->num_fds; $k++) { - if (! $this->displayed[$k] && $k != $this->key_num) { + if (! $this->displayed[$k] && $k != $this->key_num + && $k != $this->css['row_cond_num'] + && $k != $this->css['cell_cond_num'] ){ continue; } $fields[] = $this->fqn($k).' AS qf'.$k; @@ -501,7 +519,7 @@ function create_join_clause() /* {{{ */ { $tbs[] = $this->tb; - $join = $this->tb.' AS PMEtable0'; + $join = $this->tb.' AS '.$this->alias['tb']; for ($k = 0,$numfds = sizeof($this->fds); $k<$numfds; $k++) { $field = $this->fds[$k]; if($this->fdd[$field]['values']['db']) { @@ -516,7 +534,7 @@ $alias = 'PMEjoin'.$k; if (!in_array($alias,$tbs)) { $join .= " LEFT OUTER JOIN $db.$table AS $alias"; - $join .= " ON $alias.$id = PMEtable0.$field"; + $join .= " ON $alias.$id = ".$this->alias['tb'].".$field"; $tbs[]=$alias; } } @@ -524,6 +542,20 @@ return $join; } /* }}} */ + /* + * replace $tb_alias with PMEtable0 or '' and optionally $val if defined + */ + + function print_sql_sqlw_string($sql_or_sqlw = '', $subst_tb_alias = true, $val = '') /* {{{ */ + { + if ($subst_tb_alias) { + $tb_alias = $this->alias['tb'].'.'; + } else { + $tb_alias = ''; + } + return StripSlashes(eval('return "'.addslashes($sql_or_sqlw).'"; ')); + } /* }}} */ + function make_where_from_query_opts($qp = null, $text = 0) /* {{{ */ { if ($qp == null) { @@ -933,8 +965,12 @@ $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.')'; + if ($this->col_has_sql($this->key_num) && !$this->virtual($this->key_num)) { + $qparts['where'] = '('.$this->key; + } else { + $qparts['where'] = '('.$this->fqn($this->key); + } + $qparts['where'] .= '='.$this->key_delim.$this->rec.$this->key_delim.')'; $res = $this->myquery($this->query_make($qparts),__LINE__); if (! ($row = @mysql_fetch_array($res, MYSQL_ASSOC))) { @@ -1070,7 +1106,7 @@ /** * Returns CSS class name */ - function getCSSclass($name, $position = null, $divider = null, $postfix = null) /* {{{ */ + function getCSSclass($name, $position = null, $divider = null, $postfix = null, $force = null) /* {{{ */ { static $div_idx = -1; $elements = array($this->css['prefix'], $name); @@ -1079,17 +1115,21 @@ $elements[] = $this->page_types[$this->page_type]; } } - if ($position && $this->css['position']) { - $elements[] = $position; + if ($this->css['divider'] && $divider === 'next') { + $div_idx++; + if ($this->css['divider'] > 0 && $div_idx >= $this->css['divider']) { + $div_idx = 0; + } } - if ($divider && $this->css['divider']) { - if ($divider === 'next') { - $div_idx++; - if ($this->css['divider'] > 0 && $div_idx >= $this->css['divider']) { - $div_idx = 0; - } + if ($force) { + $elements[] = $force; + } else { + if ($position && $this->css['position']) { + $elements[] = $position; + } + if ($divider) { + $elements[] = $div_idx; } - $elements[] = $div_idx; } if ($postfix) { $elements[] = $postfix; @@ -1761,7 +1801,7 @@ //$raw_sort_field = 'qf'.$field; $sort_field = $this->fqn($field); $sort_field_w = $this->fdd[$field]['name']; - $this->fdd[$field]['sql'] && $sort_field_w .= ' (sql)'; + $this->col_has_sql($field) && $sort_field_w .= ' (sql)'; if ($desc) { $sort_field .= ' DESC'; $sort_field_w .= ' '.$this->labels['descending']; @@ -1948,7 +1988,7 @@ while ((!$fetched && ($row = @mysql_fetch_array($res, MYSQL_ASSOC)) != false) || ($fetched && $row != false)) { $fetched = false; - echo '',"\n"; + echo 'css['row_cond_num']]),'">',"\n"; if ($sys_cols) { /* {{{ */ $key_rec = $row['qf'.$this->key_num]; $qviewStr = $qpviewStr . '&rec='.$key_rec; @@ -2053,7 +2093,7 @@ continue; } $css_postfix = @$this->fdd[$k]['css']['postfix']; - $css_class_name = $this->getCSSclass('cell', null, true, $css_postfix); + $css_class_name = $this->getCSSclass('cell', null, true, $css_postfix, $row["qf".$this->css['cell_cond_num']]); if ($this->password($k)) { echo '',$this->labels['hidden'],'',"\n"; continue; @@ -2174,7 +2214,10 @@ for ($k = 0; $k < $this->num_fds; $k++) { if ($this->processed($k)) { $fd = $this->fds[$k]; - if ($this->readonly($k)) { + if ($this->col_has_sqlw($k)) { + $fn = $this->print_sql_sqlw_string($this->fdd[$k]['sqlw'], false, $this->get_cgi_var($this->fds[$k])); + } elseif ($this->readonly($k)) { + $fn = (string) @$this->fdd[$k]['default']; } else { $fn = $this->get_cgi_var($this->fds[$k]); @@ -2188,8 +2231,12 @@ $query .= ','.$fd; } $newvals[$this->fds[$k]] = is_array($fn) ? join(',',$fn) : $fn; - $vals_quoted[$k] = addslashes($newvals[$this->fds[$k]]); - $vals_quoted[$k] = "'".$vals_quoted[$k]."'"; + if (!$this->col_has_sqlw($k)) { + $vals_quoted[$k] = addslashes($newvals[$this->fds[$k]]); + $vals_quoted[$k] = "'".$vals_quoted[$k]."'"; + } else { + $vals_quoted[$k] = $newvals[$this->fds[$k]]; + } } } // Creating array of changed keys ($changed) @@ -2240,22 +2287,37 @@ $newvals = array(); $oldvals = array(); $changed = array(); + $changed_sqlw = array(); + $query_sqlw =''; for ($k = 0; $k < $this->num_fds; $k++) { - if ($this->processed($k) && !$this->readonly($k)) { + if (($this->processed($k) && !$this->readonly($k)) || $this->col_has_sqlw($k)) { $fd = $this->fds[$k]; $fn = $this->get_cgi_var($fd); - $newValue = $newvals[$this->fds[$k]] = is_array($fn) ? join(',',$fn) : $fn; - $newValue = addslashes($newValue); + if (!$this->col_has_sqlw($k)) { + $newValue = $newvals[$fd] = is_array($fn) ? join(',',$fn) : $fn; + $newValue = addslashes($newValue); + $newValue = '\''.$newValue.'\''; + } else { + $newValue = "@PME_SQLW_".$fd.":=".$this->print_sql_sqlw_string($this->fdd[$k]['sqlw'], false, $fn); + } if ($query_real == '') { - $query_real = 'UPDATE '.$this->tb.' SET '.$fd.'=\''.$newValue.'\''; + $query_real = 'UPDATE '.$this->tb.' SET '.$fd.'='.$newValue.''; $query_oldrec = 'SELECT '.$fd; } else { - $query_real .= ','.$fd.'=\''.$newValue.'\''; + $query_real .= ','.$fd.'='.$newValue.''; $query_oldrec .= ','.$fd; } } } - $where_part = " WHERE (".$this->key.'='.$this->key_delim.$this->rec.$this->key_delim.')'; + $where_part = " WHERE ("; + if ($this->virtual($this->key_num)) { + $where_part .= $this->print_sql_sqlw_string($this->fdd[$this->key_num]['sql'] ,false); + //modify the query to retrieve key value + $query_real .= ','.$fd.'=IF("foo"=@PME_ID:='.$this->print_sql_sqlw_string($this->fdd[$this->key_num]['sql'] ,false).','.$newValue.','.$newValue.')'.''; + } else { + $where_part .= $this->key; + } + $where_part .= '='.$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) @@ -2265,6 +2327,15 @@ // Creating array of changed keys ($changed) for ($k = 0; $k < $this->num_fds; $k++) { $key = $this->fds[$k]; + if ($this->col_has_sqlw($k)) { + if ($query_sqlw == '') { + $query_sqlw .= 'SELECT @PME_SQLW_'.$key; + } else { + $query_sqlw .= ', @PME_SQLW_'.$key; + } + $changed_sqlw[] = $changed[] = $key; + continue; + } if (! $this->processed($k) || $this->readonly($k) || $oldvals[$key] == $newvals[$key]) { continue; } @@ -2283,6 +2354,25 @@ if (! $res) { return false; } + // Getting sqlw value + if (array_count_values($changed_sqlw)) { + $res = $this->myquery($query_sqlw, __LINE__); + $sqlwvalues = @mysql_fetch_array($res, MYSQL_ASSOC); + foreach ($changed_sqlw as $key) { + $newvals[$key] = $sqlwvalues['@PME_SQLW_'.$key]; + } + } + //Update $this->rec if key value change + if (in_array($this->key, $changed)) { + $this->rec = $newvals[$this->key]; + } elseif ($this->virtual($this->key_num)) { + $res = $this->myquery('SELECT @PME_ID AS PME_ID', __LINE__); + $usermysqlvalues = @mysql_fetch_array($res, MYSQL_ASSOC); + $this->rec = $usermysqlvalues["PME_ID"]; + } else { + //failsafe, cause the morechange to be like save change + $this->rec = 0; + } // Notify list if (@$this->notify['update'] || @$this->notify['all']) { if (count($changed) > 0) { @@ -2314,10 +2404,17 @@ function do_delete_record() /* {{{ */ { + //common Query parameters (FROM and WHERE) + $endquery = 'FROM '.$this->tb.' WHERE ('; + if ($this->virtual($this->key_num)) { + $endquery .= $this->print_sql_sqlw_string($this->fdd[$this->key_num]['sql'], false); + } else { + $endquery .= $this->key; + } + $endquery .= ' = '.$this->key_delim.$this->rec.$this->key_delim.')'; // ) // Additional query - $query = 'SELECT * FROM '.$this->tb.' WHERE ('.$this->key.' = ' - .$this->key_delim.$this->rec.$this->key_delim.')'; // ) - $res = $this->myquery($query, __LINE__); + $query = 'SELECT * '.$endquery; + $res = $this->myquery($query, __LINE__); //, 0, ''); $oldvals = @mysql_fetch_array($res, MYSQL_ASSOC); @mysql_free_result($res); // Creating array of changed keys ($changed) @@ -2330,8 +2427,7 @@ } } // Real query - $query = 'DELETE FROM '.$this->tb.' WHERE ('.$this->key.' = ' - .$this->key_delim.$this->rec.$this->key_delim.')'; // ) + $query = 'DELETE '.$endquery; $res = $this->myquery($query, __LINE__); $this->message = @mysql_affected_rows($this->dbh).' '.$this->labels['record deleted']; if (! $res) { @@ -2499,6 +2595,8 @@ $this->num_fds = $field_num; $this->num_fields_displayed = $num_fields_displayed; $this->key_num = array_search($this->key, $this->fds); + isset($this->css['row_cond_field']) && $this->css['row_cond_num'] = array_search($this->css['row_cond_field'], $this->fds); + isset($this->css['cell_cond_field']) && $this->css['cell_cond_num'] = array_search($this->css['cell_cond_field'], $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. @@ -2635,10 +2733,11 @@ } elseif ($this->morechange == $this->labels['Apply']) { $this->change_enabled() && $this->do_change_record(); - $this->operation = $this->labels['Change']; // to force change operation - $this->recreate_fdd(); - $this->recreate_displayed(); - } + if ($this->rec != 0) { + $this->operation = $this->labels['Change']; // to force change operation + $this->recreate_fdd(); + $this->recreate_displayed(); + } } elseif ($this->savedelete == $this->labels['Delete']) { $this->delete_enabled() && $this->do_delete_record(); } @@ -2684,8 +2783,18 @@ $this->pw = $opts['pw']; $this->db = $opts['db']; $this->tb = $opts['tb']; - $this->key = $opts['key']; - $this->key_type = $opts['key_type']; + if (is_array($opts['key'])) { + $this->key = 'PME_MULTIPLE_KEY'; + $this->key_type = "string"; + $opts['fdd']['PME_MULTIPLE_KEY'] = Array( + 'sql' => 'concat(${tb_alias}'.join(',"_",${tb_alias}', $opts['key']).')', + 'virtual' => true, + 'options' => 'HR' + ); + } else { + $this->key = $opts['key']; + $this->key_type = $opts['key_type']; + } $this->inc = $opts['inc']; $this->options = $opts['options']; $this->fdd = $opts['fdd']; @@ -2705,6 +2814,8 @@ } $this->display['tabs'] = isset($opts['display']['tabs']) ? $opts['display']['tabs'] : true; + // Creating alias variables + $this->alias['tb'] = 'PMEtable0'; // Creating directory variables $this->dir['root'] = dirname(realpath(__FILE__)) . (strlen(dirname(realpath(__FILE__))) > 0 ? '/' : '');