<?php if (!defined('PmWiki')) exit();
/*  Copyright 2006-05-14, 2007-02-08 Ben Stallings (Ben@InterdependentWeb.com)
		based on forms.php, Copyright 2005 Patrick R. Michaud (pmichaud@pobox.com)
    This file is designed to work with PmWiki; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published
    by the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.  See pmwiki.php for full details.
		
		Database constants (DB_*) must be defined either here or in config.php.
*/

# Special handling for user info -- set this to the field that corresponds to
# a user's username
SDV($UpdateUserID,'email');

# If you want to use the open-source dFilter.js script for input masks,
# uncomment the following line; otherwise comment (#) it out:
$HTMLHeaderFmt['dFilter'] = '<script type="text/javascript" src="http://workscited.net/dFilter.js"></script>';

# $UpdateAttrs are the attributes we allow in output tags
SDV($UpdateAttrs, array('name', 'value', 'id', 'class', 'rows', 'cols',
  'size', 'maxlength', 'action', 'method', 'accesskey',
  'checked', 'disabled', 'readonly', 'enctype', 'tabindex', 'onKeyDown'));

# Set up formatting for text, submit, hidden, radio, etc. types
foreach(array('text', 'submit', 'hidden', 'password', 'radio', 'checkbox',
              'reset', 'file') as $t) 
  SDV($UpdateTags[$t][':html'], "<input type='$t' \$UpdateFormArgs />");

# (:update form:)
SDVA($UpdateTags['form'], array(
  ':args' => array('action', 'method', 'table', 'fields', 'required', 'where', 'tabindex'),
  ':html' => "<form \$UpdateFormArgs>",
	'action' => ($EnablePathInfo ? $ScriptUrl.'/'.$pagename : $ScriptUrl.'?n='.$pagename),
	'method' => 'post'));

# (:update end:)
SDV($UpdateTags['end'][':html'], '</form>');

# (:update textarea:)
SDVA($UpdateTags['textarea'], array(
  ':html' => "<textarea \$UpdateFormArgs>\$UpdateTextarea</textarea>"));
	
# (:update select:)
SDVA($UpdateTags['select'], array(
  ':args' => array('name', 'size', 'multiple', 'value', 'label', 'from', 'where', 'order', 'tabindex'),
	':html' => "<select \$UpdateFormArgs>\n\$UpdateSelectOptions</select>\n"));

Markup('update', 'fulltext', 
  '/\\(:update\\s+(\\w+)(.*?):\\)/ei',
  "UpdateMarkup(\$pagename, '$1', PSS('$2'))");

if (!function_exists('quote_smart')) {
 function quote_smart($value) { //such a useful function -- wish I remembered who wrote it
  if (get_magic_quotes_gpc()) {$value = stripslashes($value);}
  if (!is_numeric($value)) {$value = "'" . mysql_real_escape_string($value) . "'";}
  return $value;
 }
}

//define username depending on whether we're using UserAuth or AuthUser
$UpdateUsername = (defined('USER_AUTH_VERSION') ? $_SESSION['username'] : $_SESSION['authid'][0]);

SDVA($SQdata,$_REQUEST);
	
function UpdateMarkup($pagename, $type, $args) {
  global $UpdateTags, $UpdateAttrs, $InputValues, $FmtV, $UpdateFields,
	 $UpdateUserID, $UpdateUsername, $Author, $UpdateDependencies, $UpdateTabIndex, $SQdata;
	
  //this preprocessing is the same as in the InputMarkup function; only the names have been changed
	if (!@$UpdateTags[$type]) return "(:update $type $args:)";
  $opt = array_merge($UpdateTags[$type], ParseArgs($args));
  $args = @$opt[':args'];
	if (!$args) $args = array('name', 'value');
  while (count(@$opt['']) > 0 && count($args) > 0) 
    $opt[array_shift($args)] = array_shift($opt['']);
	
	if ($type == 'form') {
	 //$out .= print_r($_POST,true);
	 // Connect to Database
   $dblink = mysql_connect(DB_SERVER, DB_USER, DB_PASS) or die("Could not connect : " . mysql_error());
   mysql_select_db(DB_NAME,$dblink) or die("Could not select database: ".mysql_error());

	 if (count($_POST)>0) { // Check for required fields
		$missing=0;
	  foreach (explode(',',$opt['required']) as $req) {
		 if (($req > '') and ($_POST[$req]=='')) $missing++;
		}
		if ($missing==0) { // process form
		 $success = 0;
		 $timestamp = date('Y-m-d H:i:s');
		 
		 foreach (explode(',',$opt['where']) as $req) {
		  if (!$_POST[$req]) $missing++;
		 }
		 if ($missing==0) { //we've got all the information we need
		  unset ($where);
			unset ($dependencies);
  	  foreach (explode(',',$opt['where']) as $wherefield) {
  		 $where[] = $wherefield." = ".quote_smart($_POST[$wherefield]);
			 //prepare to delete dependent entries, if necessary
			 foreach (explode(',',$UpdateDependencies[$opt['table'].".$wherefield"]) as $dep) {
			  list($deptable,$depfield) = explode('.',$dep);
			  $dependencies[] = "DELETE FROM $deptable WHERE $depfield = ".quote_smart($_POST[$wherefield]);
			 }
  	  }
			
			if ($_POST[$opt['delete']]) { //delete an existing entry
				$query = "DELETE FROM ".$opt['table']." WHERE ".implode(' AND ',$where);
				//$out.= "<p>$query</p>";
  			if (mysql_query($query)) {
				 foreach ($dependencies as $dep) mysql_query($dep);
  			 $success = 1;
  			 $out.= "<h3 style='color:red'>Successfully deleted this record and its dependencies.</h3>";
  			} else {
  			 $out.= "<h3 style='color:red'>Unable to delete this record.</h3><p>$query</p><p>"
  			 . mysql_error()."</p>";
  			}
				
			} else { // update an existing entry
  		  $query = "UPDATE ".$opt['table']." SET ";
  			foreach (explode(',',$opt['fields']) as $field) {
  			 if ((strpos(",".$opt['null'].",",",".$field.",") !== false) AND ($_POST[$field]=='')) {
  			  $query .= "`$field` = NULL, ";
  			 } else {
  			  $query .= "`$field` = ".quote_smart($_POST[$field]).", ";
  			 }
  			}
  			if ($opt['timestamp']>'') $query .= $opt['timestamp']." = '$timestamp'";
  			
  			$query = rtrim($query, ', ')." WHERE ".implode(' AND ',$where);
  			//$out.= "<p>$query</p>";
  			if (mysql_query($query)) {
  			 $success = 1;
  			 $out.= "<h3 style='color:red'>Successfully made your changes.</h3>";
  			} else {
  			 $out.= "<h3 style='color:red'>Unable to make your changes.</h3><p>$query</p><p>"
  			 . mysql_error()."</p>";
  			}
			}
			
		 } else { // insert new entry
		  $queryA = "INSERT INTO ".$opt['table']." (";
			$queryB = ") VALUES (";
			foreach (explode(',',$opt['fields']) as $field) {
			 //is the field listed as having a default?  If not, include it.
			 if ((strpos(",".$opt['default'].",",",".$field.",") === false) OR ($_POST[$field])) {
			  $queryA .= "`$field`,";
				//if this is the UserID field and no value is given, use the UserID
			  $queryB .= quote_smart(((in_array($UpdateUserID,explode(',',$opt['where'])) and ($field==$UpdateUserID) and (!$_POST[$field])) 
			  ? $UpdateUsername : $_POST[$field])).",";
			 }
			}
			if ($opt['timestamp']>'') {
			 $queryA .= $opt['timestamp'];
			 $queryB .= "'$timestamp'";
			}
			$query = rtrim($queryA, ',').rtrim($queryB, ',').")";
			if (mysql_query($query)) {
			 $success=1;
			 $out.= "<h3 style='color:red'>Successfully added this information to the database.</h3>";
			 $wherevalue = mysql_insert_id();
			} else {
			 $out.= "<h3 style='color:red'>Unable to add this information to the database.</h3><p>$query</p><p>"
			 . mysql_error()."</p>";
			}
		 }
		} else { //missing values
		 $out .= "<h3>Please fill in all <span style='color:red'>required fields.</span></h3>\n";
		 $UpdateFields = array();
		 $UpdateFields += $_POST;
		}
	 } //endif $_POST

	 if (($success == 1) and (isset($opt['redirect']))) { //redirect to specified page
		Redirect($opt['redirect']);
	 } else {
	 
	  // Get existing info from database, if any
		unset ($where);
	  foreach (explode(',',$opt['where']) as $wherefield) {
		 if ($wherefield == $UpdateUserID) { 
	    // It's not "any kind of query," Sark.  It's a *User* query.
	    $where[] = $UpdateUserID." = ".quote_smart($UpdateUsername);
	   } else {
	    $where[] = $wherefield." = ".quote_smart($_REQUEST[$wherefield] ? $_REQUEST[$wherefield] : $wherevalue);
			SDV($SQdata[$wherefield],($_REQUEST[$wherefield] ? $_REQUEST[$wherefield] : $wherevalue));
	   }
		}
	  if ((isset($opt['table'])) and (isset($opt['fields'])) and (isset($where))) {
		 $query = "SELECT " . $opt['fields'] . " FROM " . $opt['table'] . " WHERE " . implode(" AND ",$where);
		 //$out.="$query";
	   $UpdateFields = @mysql_fetch_assoc(mysql_query($query));
		 SDVA($UpdateFields,$_POST);
		 if (defined($UpdateFields)) SDVA($SQdata,$UpdateFields);
	  }
	 }
	 mysql_close();
	//end of $type = 'form' 
	 
	//a little bit of magic to create drop-down menus from a query!
	} elseif (($type=='select') and (isset($opt['from']))) {
	 //if value and/or label are not provided, fill them in with what we do know
	 SDV($opt['value'],$opt['name']);
	 SDV($opt['label'],$opt['value']);
	 // Connect to Database
   $dblink = mysql_connect(DB_SERVER, DB_USER, DB_PASS) or die("Could not connect : " . mysql_error());
   mysql_select_db(DB_NAME,$dblink) or die("Could not select database: ".mysql_error());
	 $selectq = "SELECT ". $opt['value'] .", ". $opt['label'] ." FROM ". $opt['from']
	 ." WHERE ". ($opt['where'] ? html_entity_decode($opt['where']) : 1) 
	 . ($opt['order'] ? " ORDER BY ".$opt['order'] : "");
	 $selectd = mysql_query($selectq);
	 unset($FmtV['$UpdateSelectOptions']);
	 if (isset($opt['null'])) $FmtV['$UpdateSelectOptions'] = "<option value='' "
	 . ($UpdateFields[$opt['name']]=='' ? "selected='selected' " : "")
	 . ">" . $opt['null'] . "</option>\n";
	 while ($option = mysql_fetch_row($selectd)) {
	  $FmtV['$UpdateSelectOptions'] .= "<option value='".$option[0]."' "
		. ((($option[0]==$UpdateFields[$opt['name']]) or ($option[0]==$SQdata[$opt['name']])) ? "selected='selected' " : "")
		. ">" . $option[1] . "</option>\n";
	 }
	 //don't display database info in HTML source
	 unset($opt['value']);
	 mysql_close();
	
	} // endif $type

  // if given a parameter with no value, set the value to the name of the parameter
	// for example, "checked" should become "checked='checked'" to be valid HTML
	foreach ((array)@$opt[''] as $a)
    if (!isset($opt[$a])) $opt[$a] = $a;
		
	//insert $SQdata info into field, if value given is a parameter name in `backquotes`
	if (strrpos('`',$opt['value'])!==false) {
	 $opt['value'] = $SQdata[str_replace("`","",$opt['value'])];
	}

	if (($type=='text') or ($type=='hidden') or ($type=='password')) {
	 // insert database info into field
	 if (isset($UpdateFields[$opt['name']])) $opt['value'] = $UpdateFields[$opt['name']];
   // insert $_GET info into field, if any
	 if (isset($_GET[$opt['name']])) $opt['value'] = $_GET[$opt['name']];
	}
	
	// another bit of magic to allow values in textareas
	if ($type=='textarea')
	 $FmtV['$UpdateTextarea'] = $UpdateFields[$opt['name']]? $UpdateFields[$opt['name']]: "";
	 
	// auto-input user ID into text or hidden fields when no other value given
	if ((($type=='text') or ($type=='hidden')) and ($opt['name']==$UpdateUserID))
	 SDV($opt['value'],$UpdateUsername);
	
	//content masking with optional Javascript
	unset($opt['onKeyDown']);
	if ($opt['mask']>'')
	 $opt['onKeyDown']='javascript:return dFilter (event.keyCode, this, "'.$opt['mask'].'");';
	 
	//automatic tabindex
	if ($opt['tabindex']>0) {
	 $UpdateTabIndex = $opt['tabindex']+1;
	} elseif ($opt['tabindex']===0) {
	 $UpdateTabIndex = 0;
	} elseif (($UpdateTabIndex > 0) and ($type!='form') and ($type != 'end') and ($type != 'hidden')) {
	 $opt['tabindex'] = $UpdateTabIndex++;
	}
	 
  //not sure what this little loophole is for, but it's in forms.php, so I copied it
	if (!isset($opt['value']) && isset($InputValues[@$opt['name']])) 
    $opt['value'] = $InputValues[$opt['name']];
	
	//put quotes around values for HTML compliance
  $attr = array();
  foreach ($UpdateAttrs as $a) {
    if (!isset($opt[$a])) continue;
    $attr[] = "$a='".str_replace("'", '&#39;', $opt[$a])."'";
  }
	
	//set radio and checkboxes to match database info
	if ((($type=='radio') or ($type=='checkbox')) and ($opt['value'] == $UpdateFields[$opt['name']]))
	  $attr[] = "checked='checked'";
	
	//exit code copied bodily from forms.php
  $FmtV['$UpdateFormArgs'] = implode(' ', $attr);
  $out .= FmtPageName($opt[':html'], $pagename);
  return preg_replace('/<(\\w+\\s)(.*)$/es',"'<$1'.Keep(PSS('$2'))", $out);
}