<?php
/*
	DevSaver web framework
	copyright (c) 2002-2018 DevSaver
		web:  www.devsaver.com
		mail: support@devsaver.com
*/

if (!defined("STPBase")) {
	die("This file can't be accessed directly!");
}
class CSQLAdmin extends CLibrary {

	/**
	* description
	*
	* @var type
	*
	* @access type
	*/
	var $form;

	/**
	* description
	*
	* @var type
	*
	* @access type
	*/
	var $aclMod;
	

	/**
	* description
	*
	* @var type
	*
	* @access type
	*/
	var $functions;
		

	function __construct($section , $templates , $db , $tables , $extra = "") {
		global $_CONF;

		if (!$_GET["page"])
			$_GET["page"] = 1;				

		parent::__construct("SQLAdmin");
		
		//checking if the templates are orblects or path to a template file
		if (!is_array($templates))					
			//if path the load the tempmate form that file
			$this->templates = array("generic_form" => new CTemplate($templates));
		else
			$this->templates = $templates;
		
		$this->db = $db;
		$this->tables = $tables;
		//extra variables to be passed to cform
		$this->extra = $extra;


		if (is_array($section)) {
			$this->forms = $section;			
		} else {
		
			//loading the forms , changed the varialbes locations, but still keeping the compatibility
			$path = ($_CONF["forms"]["adminpath"] ? $_CONF["forms"]["adminpath"] : $_CONF["formspath"] );
			
			//debuging part 
//			echo "<br>FILE:SQLADMIN:MAIN:{$path}{$section}.xml";
			if (defined("PB_DEBUG") && (PB_DEBUG == "1"))
				echo "<br>FILE:SQLADMIN:MAIN:{$path}{$section}.xml";

			$conf = new CConfig( $path . $section . ".xml");

			$this->forms_path = dirname($path . $section . ".xml");

			$this->forms = $conf->vars["form"];

			//loading the edit/add forms
			if (is_array($this->forms["forms"])) {
				foreach ($this->forms["forms"] as $key => $val) {	
					$form = null;

					if (is_array($val)) {
						$form = CForm::Process($path . $val["file"]);	
						$this->forms["forms"][$key] = $form;						
						$this->forms["forms"][$key]["type"] = $val["type"];
					}
					
					if (strstr($val,"SHOW::")) {						
						$tmp = explode("::" , $val);						
						$form = is_array($this->forms["forms"][$tmp[1]]) ? $this->forms["forms"][$tmp[1]] : CForm::Process($path . $this->forms["forms"][$tmp[1]]);
						CForm::__private__showonly($form);
					} elseif (file_exists($path . $val) && trim($val)){
						$form = CForm::Process($path . $val);

					}

					if (is_array($form)) {
						$this->forms["forms"][$key] = array_merge(
									$form , 
									array(
										"table" => &$this->forms["table"],
										"table_lang" => &$this->forms["table_lang"],
										"table_uid" => &$this->forms["table_uid"],
										"urilinks" => &$this->forms["urilinks"],
										"uridata" => &$this->forms["uridata"] 
									)
								);

						if (in_array($key , array("store" , "add" , "edit" , "details" , "search")) && !isset($this->forms["forms"][$key]["type"])) {
							$this->forms["forms"][$key]["type"] = "FORM";
						} else {
							if (in_array($key , array("list" , "search")) && !isset($this->forms["forms"][$key]["type"])) {
								$this->forms["forms"][$key]["type"] = "LIST";
							}							
						}						
					}
				}
				
				//prepare buttons
				foreach ($this->forms["forms"] as $key => $val) {	
					if ((($key == "edit")||($key == "add")) && isset($this->forms["forms"][$key]["buttons"]["button_edit"])) {
						unset($this->forms["forms"][$key]["buttons"]["button_edit"]);
					}

					if (($key != "edit") && isset($this->forms["forms"][$key]["buttons"]["button_savecontinue"])) {
						unset($this->forms["forms"][$key]["buttons"]["button_savecontinue"]);
					}

					if (($key == "details") && isset($this->forms["forms"][$key]["buttons"]["button_save"])) {
						unset($this->forms["forms"][$key]["buttons"]["button_save"]);
					}

					if (!($_GET["returnurl"] || $_POST["returnurl"]) && isset($this->forms["forms"][$key]["buttons"]["button_back"])) {
						if (is_array($this->forms["forms"][$key]["buttons"]["button_back"])) {
							unset($this->forms["forms"][$key]["buttons"]["button_back"]);
						}
					}

				}					

				if (is_array($this->forms["forms"]["search"])) {
					//prepare the list to be shown under a cform box
					$search = &$this->forms["forms"]["search"];

					if (is_array($search["search"]["simple"]) && is_array($search["search"]["advanced"])) 
						$search["search"] = $search["search"][$_GET["advanced"] ? "advanced" : "simple"];					

					if (is_array($search["search"])) {
						$search_type = &$search["search"];

						$search["fields"] = array_merge((array)$search["fields"] , (array)$search_type["fields"] );
						//append a field to show all the fields when a submit button is pressed

						//prepare the list form

						//check if the fields in the list will apear dinamicaly
						if (is_array($search_type["fields"]["fields"])) {

							if (is_array($_GET["fields"])) {
								$fields_list = $_GET["fields"];
							} else {							
								$fields_list = explode("," , strlen($_GET["fields"]) ? $_GET["fields"] : $search_type["fields"]["fields"]["default"]);
							}

							//if no getfields then set the default fields
							if (!is_array($_GET["fields"]))
								$_GET["fields"] = $fields_list;

							//process the $_GET["fields"]
							if (is_array($_GET["fields"])) {
								foreach ($_GET["fields"] as $__key => $__val) {
//									if ($__key != $__val) {
										$_GET["fields"][$__val] = $__val;
										unset($_GET["fields"][$__key]);
//									}
								}

//								debug($_GET["fields"]);
								
							}
							

							
							//remove the fields which arent defined, ONLY IF $_GET[fields] is set
							if (is_array($search_type["header"]) && is_array($_GET["fields"]) ) {
								foreach ($search_type["header"] as $key => $val) {
									if (!array_exists($key , $fields_list )) {
										unset($search_type["header"][$key]);
									}							
								}						
							}

						} else {
							// add all the existing gields
							if (is_array($search_type["header"]) && count($search_type["header"]))
								$this->forms["forms"]["list"]["fields"] = array_merge($search_type["header"],$this->forms["forms"]["list"]["fields"]);
						}

					}
				}
			}
		}

		$this->form = new CForm($this->templates["generic_form"], $db , $tables);
		

}

	/**
	* description
	*
	* @param
	*
	* @return
	*
	* @access
	*/
	function FormList($items = "" , $return_ajax = false , $page = 1 , $array = false) {
		global $base , $_SESS , $site , $_MODULES;

		$found_search = true;
			
		//prepare the listing way
		if (is_array($this->forms["forms"]["search"])) {
			if ($this->forms["forms"]["search"]["search"]["required"] == "true")
				$found_search = false;			
		} else
			$found_search = true;				

		//checking if hte values weren't inputed ion the main object

		if (is_array($this->items)) {			
			$items = $this->items;
			$items_count = count($items);
		} else {

			if (is_array($items)) {

				if ($items["items"] && isset($items["count"])) {

					$sortable_fields = $items["table_fields"];
					$tmp_items = $items["items"];
					$items_count = $items["count"];
					$items = $tmp_items;

					//debug($items,1);
				} else {
					$items_count = count($items);
				}
			}
		}

		//crap, preexecute a function, which is suposed in some times to preload the items too

		//check if exists a search screen
		if (is_array($this->forms["forms"]["search"])) {
			//prepare the list to be shown under a cform box
			$search = &$this->forms["forms"]["search"];

			if (($_GET["hidesearch"] != "true")) {
				//$this->forms["forms"]["list"]["border"] = "";
				$this->forms["forms"]["list"]["subtitle"] = $this->forms["forms"]["list"]["title"];

			}

			//process the buttons
			if ($_GET["advanced"]) {
				unset($search["buttons"]["butt_advanced"]);
				unset($search["buttons"]["button_advanced"]);
			} else {
				if (isset($search)) {
					if (is_array($search["buttons"]["butt_simple"]))
						unset($search["buttons"]["butt_simple"]);

					if (is_array($search["buttons"]["button_simple"]))
						unset($search["buttons"]["button_simple"]);
				}			
			}

			if (is_array($search["search"])) {
				$search_type = &$search["search"];

				//put the remain fields in the front of the other in the listing xml
				if (is_array($search_type["header"])) {
					$this->forms["forms"]["list"]["fields"] = array_merge($search_type["header"],$this->forms["forms"]["list"]["fields"]);
				}								


				//check if exists  return url then show the return button
				if (!$_GET["returnurl"] && is_array($search["buttons"]["button_back"]))
					unset($search["buttons"]["button_back"]);
				
				//prepare the list form

				//check if the fields in the list will apear dinamicaly
				if (is_array($search_type["sql_fields"])) {

					//prepare the search query
					if (is_array($search_type["sql_fields"])) {

						

						//process the variables from the input source
						CForm::ProcessVariables($search, $_GET);


						foreach ($search_type["sql_fields"] as $key => $val) {
							//add to query only variables which are found in $_GET, others get ignored
							


							if (is_Array($val)) {

								switch (strtolower($val["type"])) {
									case "keyword":
										if (trim($_GET[$key])) {
											$_fields = explode(","  , $val["fields"]);
											$_query = null;

											switch ($val["search"]) {
												default:
												case "full":
													foreach ($_fields as $_k => $_v) {
														$_query[] = $this->db->Statement(" {$_v} LIKE '%%%s%%' " , array($_GET[$key]));
													}


													$query[] = " ( " . implode(" OR " , $_query ) . " ) ";
												break;

												case "split":
													$_data = explode(" " , $_GET[$key]);
													
													if (count($_data)) {
														foreach ($_data as $__k => $__v) {

															foreach ($_fields as $_k => $_v) {
																$_query[$_v][] = $this->db->Statement(" {$_v} LIKE '%%%s%%'" , array($__v)); 
															}
														}
													}

													if (is_array($_query) && count($_query)) {
														foreach ($_query as $_k => $_v) {

															$query[] = " ( " . implode(" OR " , $_v ) . " ) ";
														}
													}
												break;
											}
										}
										//$query[] = " ( " . implode(" OR " , $_query ) . " ) ";

										//debug($query ,1);
									break;

									case "=":
										if (isset($_GET[$key]) &&  strlen($_GET[$key])) {
											$fkey = $val["field"] ? $val["field"] : $key;
											$query[] = " {$fkey}='{$_GET[$key]}'";
										}
									break;

									case "int":
										$fkey = $val["field"] ? $val["field"] : $key;
										$query[] = " {$fkey}=" . ((int)$_GET[$key]) . "";
									break;
		
									case "%":
										if (isset($_GET[$key]) && strlen($_GET[$key])) {
											$fkey = $val["field"] ? $val["field"] : $key;
											$query[] = $this->db->Statement(" {$fkey} LIKE '%%%s%%'" , array($_GET[$key]));
										}
									break;

								}								

							} else {						
								switch (strtolower($val)) {
									case "=":
										if (isset($_GET[$key]) &&  strlen($_GET[$key]))
											$query[] = " {$key}='{$_GET[$key]}'";
									break;

									case "int":
										$query[] = " {$key}=" . ((int)$_GET[$key]) . "";
									break;
		
									case "%":
										if (isset($_GET[$key]) && strlen($_GET[$key]))
											$query[] = $this->db->Statement(" {$key} LIKE '%%%s%%'" , array($_GET[$key]));
									break;

									case "?%":
										if (isset($_GET[$key]) && strlen($_GET[$key]))
											$query[] = $this->db->Statement(" {$key} LIKE '%s%%'" , array($_GET[$key]));
									break;

									case "%?":
										if (isset($_GET[$key]) && strlen($_GET[$key]))
											$query[] = $this->db->Statement(" {$key} LIKE '%%%s'" , array($_GET[$key]));
									break;

									case "range":
										$start = "";
										$end = "";

										if ($_GET[$key . "_start"]) 
											$start = $_GET[$key . "_start"];

										if ($_GET[$key . "_end"])
											$end = $_GET[$key . "_end"];

										if ($start && $end)
											$query[] = " (({$key} <= '$end') AND ({$key} >= '$start')) ";
										else
											if ($start)
												$query[] = " {$key} >= '$start' ";
											else if ($end)
													$query[] = " {$key} <= '$end' ";									
									break;

									case "in_set":
										if ($_GET["$key"]) {
											$query[] = " FIND_IN_SET('" . $_GET[$key] . "' , `{$key}`) ";
										}																		
									break;

									case "in":
										if (strlen($_GET[$key])) {
											$__tmp = implode("','" , explode("," , $_GET[$key]));								
											$query[] = " `{$key}` IN ( '{$__tmp}' ) ";
										}									
									break;

									//prepare the fields allowed for sorting
									$__fields[] = $key;

								}						
							}
						}						

						//add the final condition to list
						if (is_array($query)) {
							
							
							if (count($query) > 1) {
								$this->forms["forms"]["list"]["sql"]["vars"]["condition"]["import"] = implode(" " . (array_exists($_GET["relation"] , array("and" , "or")) ? $_GET["relation"] : "and") . " " , $query);
							} else
								$this->forms["forms"]["list"]["sql"]["vars"]["condition"]["import"] = $query[0];
							
							if (!$this->forms["forms"]["list"]["sql"]["vars"]["req_condition"]["import"]) 
								$this->forms["forms"]["list"]["sql"]["vars"]["condition"]["import"] = " WHERE " . $this->forms["forms"]["list"]["sql"]["vars"]["condition"]["import"];
							else
								$this->forms["forms"]["list"]["sql"]["vars"]["condition"]["import"] = $this->forms["forms"]["list"]["sql"]["vars"]["req_condition"]["import"] . " AND " . $this->forms["forms"]["list"]["sql"]["vars"]["condition"]["import"];


							$found_search = true;
							
						} else {							
							if ($this->forms["forms"]["list"]["sql"]["vars"]["req_condition"]) 
								$this->forms["forms"]["list"]["sql"]["vars"]["condition"] = $this->forms["forms"]["list"]["sql"]["vars"]["req_condition"]; 
						}
						
					}

					//add the order field to the sql field
					if ($_GET["order"] && array_key_exists($_GET["order"] , $search_type["sql_fields"]))
						$this->forms["forms"]["list"]["sql"]["vars"]["order"]["import"] = $_GET["order"];
					
					//add the ordering mode to the sql vars
					if ($_GET["order_mode"] && array_exists($_GET["order_mode"] , array("ASC" , "DESC" )))
						$this->forms["forms"]["list"]["sql"]["vars"]["order_mode"]["import"] = $_GET["order_mode"];					

					//prepare the items number
					if ((int)$_GET["items"])
						$this->forms["forms"]["list"]["items"] = $this->forms["forms"]["list"]["sql"]["vars"]["items"]["import"] = (int)$_GET["items"];
					else
						$this->forms["forms"]["list"]["sql"]["vars"]["items"]["import"] = $this->forms["forms"]["list"]["items"];					
				
				}
				
			} else {
				//required condition
				$this->forms["forms"]["list"]["sql"]["vars"]["condition"] = $this->forms["forms"]["list"]["sql"]["vars"]["req_condition"]; 
			}
		}



		if ($found_search || ($_GET["search"])) {



			$_GET["page"] = $_GET["page"] ? $_GET["page"] : 1;
			//auto index the element
			$start = $this->forms["forms"]["list"]["items"] * ($_GET["page"] - 1 );

			if (is_array($items) && count($items)) {

				if ($items["list"] && is_array($items["list"])) {

					foreach ($items["list"] as $key => $val) {
						$items["list"][$key]["_count"] = ++$start;
					}			

				} else {


					if (!array_key_exists("list" , $items) && !array_key_exists("items" , $items)) {
						foreach ($items as $key => $val) {
							$items[$key]["_count"] = ++$start;
						}			
					} else {

						unset($items["list"]);
					}
				}
			}		

			$this->form->functions["process_records"] = $this->functions["list_process"];
			$this->form->functions["pre_process_records"] = $this->functions["list_preprocess"];

		
			if (is_array($this->functions["list"])) {
				call_user_func_array($this->functions["list"], array($items , $items_count));
			}

			//check if is a normal request or an ajax request
			if ($return_ajax) {
//				debug($items,1);
//				return $this->form->AjaxList($this->forms["forms"]["list"] , $items , $items_count , $this->extra["list"] , $page);

				return $this->form->SimpleList($this->forms["forms"]["list"] , $items , $items_count , $this->extra["list"] , null , false);

			} else {		
				//$data = new CForm($this->templates["generic_form"], &$this->db , &$this->tables);

				if ($array == false) {

					//prepare the items

					if (count($items)) {
							$arr_data = array(
								"items"			=> $items,
								"table_fields"	=> $sortable_fields,
								"count"			=> $items_count
							);
					} else {
							$arr_data = null;
					}
										


					$return = $this->form->SimpleList(
							$this->forms["forms"]["list"] , 
							$arr_data, 
							$items_count , 
							is_array($this->extra) ? $this->extra["list"] : ""
					);


				} else {				
					return $this->form->SimpleList($this->forms["forms"]["list"] , $items , $items_count , $this->extra["list"] , null , true);
				}
			}

		}

		//at this stage remove the unused sections
		unset($search["search"]);

//		debug($this->templates["generic_form"],1);

		if (is_array($search) && ($_GET["hidesearch"] != "true")) {			
			$search_form = new CForm($this->templates["generic_form"], $this->db , $this->tables);
			return $search_form->Show($search , array("values"=>$_GET) , array("after" => $search["after"] . $return));
		} else
			return $return;
		
	}

	/**
	* description
	*
	* @param
	*
	* @return
	*
	* @access
	*/
	function SetFunction( $form , $event , $function) {
		$this->functions[$form][$event] = $function;
	}
	

	/**
	* description
	*
	* @param
	*
	* @return
	*
	* @access
	*/
	function ListProcess($pre = "" , $after = "" ) {
		$this->functions["list"]["pre"] = $pre;
		$this->functions["list"]["after"] = $after;
	}

	/**
	* description
	*
	* @param
	*
	* @return
	*
	* @access
	*/
	function RidCond($uid , $vars) {
		$tmp = explode("," , $uid);

		foreach ($tmp as $k => $v) {

			if ((int)$vars[$v]) {
				$cond[] = "`{$v}` = " . $vars[$v] ." ";
			} else {							
				$cond[] = "`{$v}` = '" . $vars[$v] ."' ";
			}
		}

		$cond = implode(" AND " , $cond);

		return $cond;

	}
	
	/**
	* description
	*
	* @param
	*
	* @return
	*
	* @access
	*/
	function StoreRecord($redirect = true) {
		global $base, $_CONF , $_LANG_ID;

		//debug($_POST,1);


		//validating the input data
		if ($_SERVER["REQUEST_METHOD"] == "POST") {

			$uid_cond = $this->RidCond($this->forms["table_uid"] , $_POST);									


			//doing a autodetect for storing type , edit or add
			//if $_GET["type"]	is set is simple, else detecting after the id form
			if (!isset($_GET["type"])) {

				$tmp = explode("," , $this->forms["table_uid"]);

				$edit = true;

				foreach ($tmp as $key => $val) {
					if (!$_POST[$val]) {
						$edit = false;
					}					
				}

				$_GET["type"] = $edit ?"edit" : "add";
				
			}	

			//if validation succeeds then i move the files from /tmp to their directory, else i will proceed to add
			//precheck for uploaded files, like temporary images, etc.
			$form = $this->forms["forms"][$_GET["type"]];



			if (is_array($form["fields"])) {
/*
				
				$form_fields = array();
				foreach ($form["fields"] as $key => $val) {

					if ($key == "box") {
						foreach ($form["fields"]["box"] as $k => $v) {							

							if (is_array($v["fields"])) {
								$form_fields = array_merge(
									$v["fields"],
									$form_fields
								);
							}
							
						}				
					} else {					
						$form_fields[$key] = $val;
					}

				}				
*/
				$form_fields = CForm::AllFields($form);

			} 
			
			if (is_array($form_fields)) {

				$_POST = CForm::ProcessVariables(
					array(
						"fields"	=> $form_fields
					), 
					$_POST
				);



				foreach ($form_fields as $key => $val) {
					//update the name value
					if (!$val["name"])
						$val["name"] = $key;
				
					switch ($val["type"]) {


						case "checkbox":
							if ($this->_set_store_nochecks != true) {
								if (!isset($_POST[$key])) {
									$_POST[$key] = "0";
								}
							}							
						break;

						case "upload":
							$file = true;
						case "image":
							unset($_POST[$key]);

							CForm::__private_uploads_pre($val , $_fields);
							
						break;
					}							
				}						

			}



			//if not default language then unvalidate the form
			if ($_REQUEST["lang_id"]) {
				$lang = CXMLFormLanguage::GetLanguage($_REQUEST["lang_id"]);

				if (!$lang["default"]) {
					$_GET["FORMvalidate"] = "false";
				}
				
			}
			

			//force for no validation sometimes
			if ($_GET["FORMvalidate"] == "false") {
				$fields = "";
			} else {
				$fields = $this->form->Validate(
					array(
						"fields"	=> $form_fields,
						"table_uid"	=> $form["table_uid"] , 
						"table"		=> $form["table"],
						"table_lang"	=> $form["table_lang"],
					), 
					$_POST
				);
			}


			if (is_array($fields) && ($_GET["ajax"] == "true")) {

				header("Content-Type: application/json; charset=utf-8");				
						
				return json_encode(
					array(
						"errors"	=> $fields["errors"],
						"error"		=> $fields["error"],
					)
				);

			}
			
				
			if (!is_array($fields)) {
				//adding to database

				if ($this->functions["onstore_prepare"]) {
					$vars = call_user_func($this->functions["onstore_prepare"] , $_POST , $this->forms);
				}

				//check if its an isert
				if (is_array($this->db->QFetchArray("SELECT * FROM " . $this->tables[$this->forms["table"]] . " WHERE {$uid_cond}"))) {

					$this->db->QueryUpdate($this->tables[$this->forms["table"]] , $_POST , $uid_cond );

					//update the language file too				

					$id = $_POST[$this->forms["table_uid"]];
					$was_added = false;
				} else { 

					$id = $this->db->QueryInsert($this->tables[$this->forms["table"]] , $_POST);

					$_POST[$this->forms["table_uid"]] = $id;
					$was_added = true;

					//regenerate the condition
					$uid_cond = $this->RidCond($this->forms["table_uid"] , $_POST);									
					
					//if i have an ordering function then auto generate the id
					if (is_array($this->forms["forms"]["list"]["order"])) {

						$ofield = $this->forms["forms"]["list"]["order"]["field"];

						$this->db->Query(
							"UPDATE {$this->tables[$this->forms['table']]} SET {$ofield}={$id} WHERE {$this->forms[table_uid]}={$id}"
						);

						//remove the order field

						unset($_POST[$ofield]);

					}
					
				}	
				
				//update the language data
				if ($this->forms["table_lang"]) {

					if ($this->forms["forms"]["edit"]["lang"] == "false") {
						$lid = "0";
					} else {
						$lid = $_POST["lang_id"];
					}

					$old_lang = $this->db->QFetchArray(
						"SELECT * FROM " . $this->tables[$this->forms["table_lang"]] . " WHERE " . 
						"{$uid_cond} AND " . 
						"lang_id={$lid} "
					);		
					
					$data = $_POST;
					$data["lang_id"] = $lid;

					if (is_Array($old_lang)) {
						$this->db->QueryUpdate(
							$this->tables[$this->forms["table_lang"]] , 
							$data,
							"{$uid_cond} AND lang_id={$lid} "
						);
					} else {					

						$this->db->QueryInsert(
							$this->tables[$this->forms["table_lang"]] , 
							$data
						);

					}
					
				}


				//data stored, taking care of uploade files/images, etc				
				if (is_array($form_fields)) {
					foreach ($form_fields as $key => $val) {

						//update the name value
						if (!$val["name"])
							$form_fields[$key]["name"] = $val["name"] = $key;

						switch ($val["type"]) {
							case "upload":
							case "image":


								//checking if is really e file, else if no tmp is set then it can be the folder where are stored the values
								if (CForm::__private_uploads_after($val)) {
									$_POST[$key] = 1;

									$this->db->QueryUpdate(
										$this->tables[$this->forms["table"]] , 
										$_POST , 
										$uid_cond 
									);

									if ($this->forms["table_lang"]) {
										$this->db->QueryUpdate(
											$this->tables[$this->forms["table_lang"]] , 
											$_POST , 											
											"{$uid_cond} AND lang_id={$_POST[lang_id]} "
										);
									}
								}

							break;

							default:
								if (is_array($val["file"]))
									SaveFileContents(
										$_CONF["path"] . $_CONF["upload"] . $val["file"]["path"] . $val["file"]["default"] . $_POST[$val["file"]["field"]] . $val["file"]["ext"] , 
										//just changed
										/*stripslashes*/($_POST[$key])
									);
							break;

						}
					}


					//clean files
					foreach ($form_fields as $key => $val) {
						switch ($val["type"]) {
							case "upload":
							case "image":
								CForm::__private_uploads_clean($val);
							break;
						}
					}

				}

				if (!$_GET["type"]) {
					$_GET["type"] = $_POST[$this->forms["table_uid"]] ? "edit" : "add";
				}

				if ($this->functions["onstore"])
					call_user_func($this->functions["onstore"] , $_POST , $this->forms);


				//$this->templates["generic_form"]->blocks["Temp"]->input = $this->forms["forms"][$_GET["type"]]["redirect"];
				//replacing the values
				//die($this->templates["generic_form"]->blocks["Temp"]->Replace($_POST));

				//do this before anything
				if ($_POST["_after_save"]) {
					$_POST["after_save"] = $_POST["_after_save"];
				}				
				
				if ($_POST["after_save"]) {
					$vars = $this->form->GlobalVars($this->forms["forms"]["add"] , array_merge($_GET , $_POST)); 
					//the user wants to add another record after he adds the current one, so lets help him do it easy

					UrlRedirect(
						CTemplateStatic::Replace(
							$vars["self.uri.add"] . "&after_save={$_POST[after_save]}&returnurl=" . $_POST["returnurl"],
							$_GET , 
							$_POST
						)
					);
				}


				if ($_POST["redir_lang_id"]) {
	
					$x = parse_url($_POST["request_uri"]);
					parse_str($x["query"] , $data);

					$data["lang_id"] = $_POST["redir_lang_id"];

					//its an add operation, need to alter the redirect to go to edit
					if ($was_added) {
						$data[$this->forms["table_uid"]] = $_POST[$this->forms["table_uid"]];
						$data["action"] = $this->forms["uridata"]["edit"];
					}
					

					header("Location:" . basename($_SERVER["SCRIPT_NAME"]) . "?" . http_build_query($data));
					exit;
				}
								

				if ($_GET["returnURL"]) {
					header("Location:" . urldecode($_GET["returnURL"]));
					exit;
				}

				if ($_POST["returnurl"]) {

					switch ($_GET["storeredirect"]) {

						case "STOREDETAILS":
							header("Location:" . basename($_SERVER["SCRIPT_NAME"]) . "?mod={$_GET[mod]}&sub={$_GET[sub]}&action={$this->forms[uridata][details]}&{$this->forms[table_uid]}={$_POST[$this->forms[table_uid]]}&returnurl={$_POST[returnurl]}");
							exit;
						break;

						case "ADDDETAILS":

							//if is a <new></new> adition the redirect to details
							if ($was_added) {
								header("Location:" . basename($_SERVER["SCRIPT_NAME"]) . "?mod={$_GET[mod]}&sub={$_GET[sub]}&module_id={$_GET[module_id]}&action={$this->forms[uridata][details]}&{$this->forms[table_uid]}={$_POST[$this->forms[table_uid]]}&returnurl={$_POST[returnurl]}");
								exit;
							} 
							//else co in next case
							
						default:
							$count = 1;
							while ($count < 10 ) {
								$_POST["returnurl"] = urldecode($_POST["returnurl"]);
								if ((substr($_POST["returnurl"],0,1) == "/") || stristr($_POST["returnurl"] , "?"))
									break;

								$count ++;
							}

							//$this->templates["generic_form"]->blocks["Temp"]->input = $_POST["returnurl"];					
							header("Location:" . CTemplateStatic::Replace($_POST["returnurl"] , array_merge($_GET,$_POST)) );
							exit;
						break;

					}
				
				}
				
				if ($redirect == true) {
					header("Location: " . CTemplateStatic::Replace($this->forms["forms"]["add"]["redirect"] , array_merge($_GET,$_POST)));
					exit;
				} else {
					return true;
				}
			}
								
		} else {
			die("You cant access this link directly!<br><a href='index.php'>Click here</a> to reload the CMS.");
			//redirecting to list page
			header("Location:" . str_replace("&action=store" , "" , $_SERVER["REQUEST_URI"]));
			exit;
		}				

		
		if (is_array($_fields["values"]))
			// read the default record, and merge the fields
			$fields["values"] = array_merge($fields["values"], $_fields["values"]);			

		if ($_POST[$this->forms["table_uid"]]) {			
			$data = $this->db->QFetchArray("SELECT * FROM " . $this->tables[$this->forms["table"]] . " WHERE `" . $this->forms["table_uid"] . "`='" . $_POST[$this->forms["table_uid"]] . "'" );
			
			$fields["values"] = array_merge((array)$data , (array)$fields["values"]);
	//		debug($fields);
		}			

		
		return $this->form->Show($this->forms["forms"][$_GET["type"]] , $fields , $this->extra[$_GET["type"]]);				
	}
	
	/**
	* description
	*
	* @param
	*
	* @return
	*
	* @access
	*/
	function RestoreURI($section) {
		if (is_array($_GET)) {
			foreach ($_GET as $key => $val) {
				$out[$key] = $key . "=" . $val;
			}
						
			$out[$this->forms["uridata"]["action"]] = $this->forms["uridata"]["action"] . "=" . $this->forms["uridata"][$section];
			unset($out[$this->forms["table_uid"]]);

			return CryptLink($_SERVER["SCRIPT_NAME"] . "?" . implode("&" , $out));

			//return $_
		}		
	}
	

	/**
	* description
	*
	* @param
	*
	* @return
	*
	* @access
	*/
	function DoEvents($section = ""  , $extra = "" , $values = "") {
		global $base , $_CONF , $_MODULES;

		if (is_array($extra)) {
			$this->extra = array_merge($this->extra , $extra);
		}

		if ($this->forms["functions"]) {
			foreach ($this->forms["functions"] as $key => $val) {

				$this->functions[$key] = array(&$_MODULES[$val["module"]] , $val["function"]);
			}
			
		}
		


		$this->ProcessFunctions("add");
		$this->ProcessFunctions("edit");
		$this->ProcessFunctions("details");
		$this->ProcessFunctions("list");
		$this->ProcessFunctions("search");


		switch ($_GET[$this->forms["uridata"]["action"]]) {

			case $this->forms["uridata"]["delete"]:

				if (!$this->hasAccess("delete")) {
					return $this->denyAccess();
				}
				

				if (($_GET["rconfirm"] == "true")&&($_GET["confirmed"] != "true")) {
					return $this->templates["generic_form"]->blocks["DeleteItem"]->Replace(array(
									"title" => $_GET["title"] ? urldecode($_GET["title"]) : "Delete Item",
									"description" => $_GET["description"] ? urldecode($_GET["description"]) : "Are you sure you want to delete this record?",
									"return" => urldecode($_GET["returnURL"]),
									"cancel_location" => urldecode($_GET["returnURL"]),
									"delete_location" => $_SERVER["REQUEST_URI"] . "&confirmed=true"
								));
				}

				if ($_SERVER["REQUEST_METHOD"] == "POST") {

					if (is_array($_POST[$this->forms["table_uid"]])) {
						foreach ($_POST[$this->forms["table_uid"]] as $key => $val) {
							$this->db->Query("DELETE FROM " . $this->tables[$this->forms["table"]] . " WHERE `" . $this->forms["table_uid"] . "`='" . $val . "'" );

							if ($this->forms["table_lang"]) {
								$this->db->Query("DELETE FROM " . $this->tables[$this->forms["table_lang"]] . " WHERE `" . $this->forms["table_uid"] . "`='" . $val . "'" );
							}
						}
					}


					if ($_GET["returnURL"]) {
						header("Location: " . CryptLink(urldecode($_GET["returnurl"])));
						exit;
					} else {
						header("Location:" . $_SERVER["HTTP_REFERER"]/*$this->RestoreURI("list")*/);
						exit;
					}

				} else {
				
					//searching for element
					$data = $this->db->QFetchArray("SELECT * FROM " . $this->tables[$this->forms["table"]] . " WHERE `" . $this->forms["table_uid"] . "`='" . $_GET[$this->forms["table_uid"]] . "'" );

					//check for multilanguage table existence
					if ($this->forms["table_lang"]) {
						$data2 = $this->db->QFetchArray(
							"SELECT * FROM 	" . $this->tables[$this->forms["table_lang"]] . " ".
							"WHERE {$this->forms['table_uid']} ='" . $_GET[$this->forms["table_uid"]] . "' AND	lang_id={$_GET[lang_id]}" 
						);

						if (is_array($data2)) {
							$data = array_merge(
								$data , 
								$data2
							);
						}
						
					} 

					//checking if this is a valid data
					if (is_array($data)) {

						if ($this->functions["ondelete"]) {
							call_user_func($this->functions["ondelete"] , $data , $this->forms);
						}


						$this->db->Query("DELETE FROM " . $this->tables[$this->forms["table"]] . " WHERE `" . $this->forms["table_uid"] . "`='" . $_GET[$this->forms["table_uid"]] . "'" );

						if ($this->forms["table_lang"]) {
							$this->db->Query("DELETE FROM " . $this->tables[$this->forms["table_lang"]] . " WHERE `" . $this->forms["table_uid"] . "`='" . $_GET[$this->forms["table_uid"]] . "'" );
						}

						if ($this->functions["onpostdelete"])
							call_user_func($this->functions["onpostdelete"] , $data , $this->forms);

					}


				
					if ($_GET["returnURL"]) {

						$tmp = parse_url($_GET["returnURL"]);
						parse_str($tmp["query"] , $vars);

						if (is_array($vars)) {
							foreach ($vars as $key => $val) {

								switch ($key) {
									case "returnURL":
									case "returnurl":
										if (stristr($val , "/")) {
											$vars[$key] = urlencode(urlencode($val));
										} elseif( stristr(urldecode($val) , "/")){
											$vars[$key] = urlencode($val);
										}
									break;
								}								
							}							
						}

						$tmp = $tmp["path"] . "?" . http_build_query($vars);

						header("Location: " . CryptLink(urldecode($tmp)));
						exit;
					} else {
						header("Location:" . $_SERVER["HTTP_REFERER"]/*$this->RestoreURI("list")*/);
						exit;
					}
				}
				
			break;

			case $this->forms["uridata"]["store"]:

				if (!$this->hasAccess("store")) {
					return $this->denyAccess();
				}

				return $this->StoreRecord();
			break;

			case $this->forms["uridata"]["add"]:
				if (!$this->hasAccess("add")) {
					return $this->denyAccess();
				}


				if (is_array($values)) {
					$fields["values"] = $values["add"];
				}

				if ($this->functions["onadd"]) {
					$data = call_user_func($this->functions["onadd"] , $data, $this->forms);
				}

				if ($this->functions["onadd_form"]) {
					$this->forms["forms"]["add"] = call_user_func($this->functions["onadd_form"] , $data , $this->forms["forms"]["add"]);
				}

				
				return $this->form->Show($this->forms["forms"]["add"] , $fields , $this->extra["add"]);
			break;

			case $this->forms["uridata"]["edit"]:
				//searching for element
				if (!$this->hasAccess("edit")) {
					return $this->denyAccess();
				}

				$this->ProcessExtra("edit");

				if (is_array($values) && is_array($values["edit"])) {
					$data = $values["edit"];
				} else {
	

					
					//if no tables then no database query
					if ($this->forms["table"]) {

						$cond = $this->RidCond($this->forms["table_uid"] , $_GET);									

						$data = $this->db->QFetchArray("SELECT * FROM " . $this->tables[$this->forms["table"]] . " WHERE {$cond}" );

						//check for multilanguage table existence
						if ($this->forms["table_lang"]) {

							if ($this->forms["forms"]["edit"]["lang"] == "false") {
								$lid = "0";
							} else {
								$lid = $_GET["lang_id"];
							}
							

							$data2 = $this->db->QFetchArray(
								"SELECT * FROM 	" . $this->tables[$this->forms["table_lang"]] . " ".
								"WHERE {$cond} AND	lang_id=%d" ,
								array($lid)
							);

							if (is_array($data2)) {
								$data = array_merge(
									$data , 
									$data2
								);
							}
							
						} 
					}
					

				}



				if ($this->functions["onedit"])
					$data = call_user_func($this->functions["onedit"] , $data, $this->forms);

				if ($this->functions["onedit_form"]) {
					$this->forms["forms"]["edit"] = call_user_func($this->functions["onedit_form"] , $data , $this->forms["forms"]["edit"]);
				}


				//checking if this is a valid data
				if (is_array($data)) {
					$fields["values"] = $data;
					return $this->form->Show($this->forms["forms"]["edit"] , $fields , $this->extra["edit"]);
				} 

				header("Location:" . $this->RestoreURI("list"));
				exit;
				
			break;

			case $this->forms["uridata"]["details"]:
				if (!$this->hasAccess("details")) {
					return $this->denyAccess();
				}

				$this->ProcessExtra("details");

				if (is_array($values) && is_array($values["details"])) {
					$data = $values["details"];
				} else {

					//if no tables then no database query
					if ($this->forms["table"]) {


						$cond = $this->RidCond($this->forms["table_uid"] , $_GET);									

						//searching for element
						$data = $this->db->QFetchArray("SELECT * FROM " . $this->tables[$this->forms["table"]] . " WHERE {$cond}" );

						//check for multilanguage table existence
						if ($this->forms["table_lang"]) {

							if ($this->forms["forms"]["edit"]["lang"] == "false") {
								$lid = "0";
							} else {
								$lid = $_GET["lang_id"];
							}

							$data2 = $this->db->QFetchArray(
								"SELECT * FROM 	" . $this->tables[$this->forms["table_lang"]] . " ".
								"WHERE {$cond} AND	lang_id={$lid}" 
							);

							if (is_array($data2)) {
								$data = array_merge(
									$data , 
									$data2
								);
							}
							
						} 
					}
				}


				if ($this->functions["ondetails"]) {
					$data = call_user_func($this->functions["ondetails"] , $data , $this->forms);
				}

				if ($this->functions["ondetails_form"]) {
					$this->forms["forms"]["details"] = call_user_func($this->functions["ondetails_form"] , $data , $this->forms["forms"]["details"]);
				}

				//checking if this is a valid data
				if (is_array($data)) {
					$fields["values"] = $data;
					return $this->form->Show($this->forms["forms"]["details"] , $fields, $this->extra["details"]);
				} 

				header("Location:" . $this->RestoreURI("list"));
				exit;
				
			break;

			case "ajax.download-file":

				if ($this->forms["table"]) {


					$cond = $this->RidCond($this->forms["table_uid"] , $_GET);									

					//searching for element
					$data = $this->db->QFetchArray("SELECT * FROM " . $this->tables[$this->forms["table"]] . " WHERE {$cond}" );

					//check for multilanguage table existence
					if ($this->forms["table_lang"]) {
						$data2 = $this->db->QFetchArray(
							"SELECT * FROM 	" . $this->tables[$this->forms["table_lang"]] . " ".
							"WHERE {$cond} AND	lang_id={$_GET[lang_id]}" 
						);

						if (is_array($data2)) {
							$data = array_merge(
								$data , 
								$data2
							);
						}						
					} 
				}

				//read the field
				if ($this->functions["ondownload"])
					$data = call_user_func($this->functions["ondownload"] , $data, $this->forms);


				$field = CForm::GetField($this->forms["forms"]["add"] , $_GET["field"]);

				$path = ($GLOBALS["_ADMIN"] ? "../upload/" : "upload/") . 
						$field["path"] . 
						$field["file"]["default"] . 
						$data[$field["file"]["field"]] . 
						$field["file"]["ext"];

				if (file_exists($path)) {
					$mime = new CMime();
					$mime->Set("unknown");
					$mime->Filename($data[$_GET["field"] . "_file"]);

					CFile::ReadChunked($path);
					die();
				} else {
					throw new Exception("File '{$path}' doesnt exists!");
						
				}
				

			break;

			case "ajax.reorder-records":
				if (!$this->hasAccess("reorder")) {
					return $this->denyAccess();
				}


				if ($this->forms["forms"]["list"]["order"]) {
					//this can be time consuming
					//set_time_limit(0);

					//shit
					if ($_POST["table_order"] && is_array($this->forms["forms"]["list"]["order"])) {

						//debug($_GET,1);

						$order = $this->forms["forms"]["list"]["order"];

						//read the items
						$items = $this->db->QFetchRowArray("SELECT {$this->forms[table_uid]} as id, {$order[field]} as oid FROM " . $this->tables[$this->forms["table"]] . " WHERE {$this->forms[table_uid]} in (" . implode("," , $_POST["table_order"]) . ") ORDER BY {$order[field]} {$order[mode]}" );

						if (is_array($items) && (count($items) == count($_POST["table_order"]))) {

							//invert the key with vars from new order
							foreach ($_POST["table_order"] as $key => $val) {
								$new_order[$val] = $key;
							}
							

							foreach ($items as $key => $val) {
								$items[$key]["noid"] = $items[$new_order[$val["id"]]]["oid"];
							}
							
							foreach ($items as $key => $val) {
								$this->db->QueryUpdate(
									$this->tables[$this->forms["table"]],
									array(
										$order["field"]	=> $val["noid"]
									),
									"{$this->forms[table_uid]} = {$val[id]}"
								);
							}
							
							die("1");
						}
					}

					die("0");
				}

				die("0");
							
			break;

			case $this->forms["uridata"]["search"]:
			case $this->forms["uridata"]["list"]:
			default:		

				if (!$this->hasAccess("list")) {
					return $this->denyAccess();
				}

				if ($this->functions["load_records"]) {
					$values["list"] = call_user_func($this->functions["load_records"] , $data , $this->forms);

					if ($values["values"]["norecords"]) {
						$this->forms["list"]["norecords"] = $values["values"]["norecords"];
					}
					
				}

				if ($_GET["ajax"] == "true") {
					echo $this->FormList($values["list"] , true , $_GET["page"]);
					die();
				} else {				
					if (is_Array($values) && is_array($values["list"])) {
						return $this->FormList($values["list"]);
					} else {
						return $this->FormList($values);
					}
					
				}
			break;

		}	
	}


	/**
	* description
	*
	* @param
	*
	* @return
	*
	* @access
	*/
	function ProcessFunctions($type) {
		global $_MODULES;

		if ($this->forms["functions"][$type]) {
			$func = $this->forms["functions"][$type]["function"];
			$mod = $this->forms["functions"][$type]["module"];

			if ($_MODULES[$mod] && method_exists($_MODULES[$mod] , $func)) {
				$_MODULES[$mod]->$func($this->forms["forms"][$type]);
			}			
		}		
	}
	
	/**
	* description
	*
	* @param
	*
	* @return
	*
	* @access
	*/
	function ProcessExtra($type) {	

		if (!is_array($form = $this->forms["forms"][$type])) {
			return "";
		}

	
		if (!is_array($after = $this->forms["after"][$type])) {
			return "";
		}

		if (!is_array($after[key($after)])) {
			$after = array(0 => $after);
		}
		

		
		foreach ($after as $key => $val) {

			switch ($val["type"]) {
				case "sqladmin":	

					if (!$val["restricted"] || ($val["restricted"] && !CForm::__isRestricted($val["restricted"]))) {


						if (is_array($val["xml"])) {

							foreach ($val["xml"] as $key => $val) {
								$data = new CSQLAdmin($val , $this->templates,$this->db,$this->tables);
								$data->setAclMod($this->aclMod);
								$data->functions = $this->functions["after"];
								$this->extra[$type]["after"] .= $data->DoEvents();
							}					
						} else {

							$data = new CSQLAdmin($val["xml"] , $this->templates,$this->db,$this->tables);
							$data->setAclMod($this->aclMod);
							$data->functions = $this->functions["after"];
							$this->extra[$type]["after"] .= $data->DoEvents();				
						}
					}
				
				break;
			}

		}
		

	}

	
	/**
	* description
	*
	* @param
	*
	* @return
	*
	* @access
	*/
	function setAclMod($mod) {
		$this->aclMod = $mod;
		$this->form->setAclMod($mod);
	}


	/**
	* description
	*
	* @param
	*
	* @return
	*
	* @access
	*/
	function hasAccess($type) {
		global $base;

		if (!is_array($this->forms["acl"])) {
			return true;
		}
		
		if ($type == "store") {
			return $this->hasAccess("edit") || $this->hasAccess("add");
		}

		
		if ($this->forms["acl"] && $this->aclMod && !$base->acl->checkModRule($this->aclMod , $this->forms["acl"][$type])) {
			return false;
		}
		
		return true;		
	}
	
	/**
	* description
	*
	* @param
	*
	* @return
	*
	* @access
	*/
	function denyAccess() {
		global $base;

		//die("dies in sqladmin ");
		urlredirect("index.php?mod=denied&sub=landing");
	}
	
}

/*

History

v0.0.4
	Unreleased
		Fixed the saving the value in a file, added stripslashes

v0.0.3
	Wensday 24 March 2004
		Moved SimpleList from sqladmin in forms class
		Added image element to SimpleList
		Added date element to SimpleList	
		Instead of $form array the data can be a path to an xml file
		The template is passed to sql admin, no longer loading from generic_form

v0.0.2
	Tuesday 16 March 2004
		Fixed, add/edit SQL query.

	Sunday 14 March 2004
		Added search support for list section.
		Added header titles to list section.
		Fixed the buttons apearance in list. ( they dont apear broken anymore )
		Added upload/resize/efects image form to forms library, FUCK loosing the image if the forms isnt complety
		validated from first time.
		Added html editor to forms library.		
		Fixed the image loosing when the form wasnt validated.
		Added the download from web image.

v0.0.1
	Wensday 3 March 2004 
		First version with basic options, edit, list, add.

*/
?>