<?php
	require_once(dirname(__FILE__).DIRECTORY_SEPARATOR.'class.api.php');

	class API_CUSTOMFIELD extends API //Implements Faux interface 'ManageTableHook' (readForManageTable / readForManageTableCountQuery)
	{
		var $fields = array (
			'customfieldid',
			'name',
			'type'
		);

		var $pk = 'customfieldid';
		
		var $customfieldid = 0;
		var $name = '';
		var $type;
		
		var $customFieldDataArray = array();
		
		var $customFieldAllowableTypes = 
			array (
				CF_TYPE__MULTI_CHECK,
				CF_TYPE__FREE_FORM
			);

		/**
		* Constructor
		*
		* @param
		* @return null
		*/
		function API_CUSTOMFIELD($id=false,$getData=false) {
			parent::API();
			
			if ((int)$id > 0) {
				$this->read($id,$getData);
			}
		}

		/**
		* Create a new item in the database
		*
		* @return mixed false if failed to create, the id of the item otherwise
		*/
		function create()
		{
			return parent::create();
		}
		
		/**
		* save
		* save the custom field back to the database
		*
		* @return bool was the save successful ?
		*/
		function save()
		{
			return parent::save();
		}

		/**
		* delete
		* Delete a custom field, delete any data it may contain and any question links it may have.	
		*
		* @param int $id The id of the category to delete
		*
		* @return bool Was the delete successful ?
		*/
		function delete($id=0)
		{
			if (!parent::delete($id)) {
				return false;
			}

			return true;
		}
		
		/**
		* read
		* Reads a customfield by ID.
		*
		* @type static
		* @param int $id The id of the customfield
		* @param bool $getData 
		*
		* @return API_CUSTOMFIELDS object
		*/
		function read($id,$getData=false) {
			$this->load($id);
			
			if ($getData) {
				$cfData = new API_CUSTOMFIELDS_DATA();
				$this->customFieldDataArray = $cfData->loadMulti(array($id=>$id),$this->pk,false,"data ASC");
			}
		}
		
		/**
		* readAll
		* Reads all customfields into an object array
		*
		* @type static
		* @param int $id The id of the customfield
		* @param bool $getData 
		*
		* @return API_CUSTOMFIELDS object
		*/
		function readAll() {
			parent::setupDatabase();

			$query = "
				SELECT 
					cf.*,
					cfq.data,
					cfq.customfield_dataid
				FROM
					".$GLOBALS['tablePrefix']."customfields cf LEFT JOIN ".$GLOBALS['tablePrefix']."customfields_data cfq ON (cf.customfieldid = cfq.customfieldid)
				ORDER BY cfq.data ASC
			";
			
			$result = $this->db->Query($query);
			
			return API_CUSTOMFIELD::populateCustomFieldObjs($result);
		}
		
		/**
		* readForManageTable
		* Reads all customfields specifically for display in tabular form. Returns a database resource.
		*
		* @type static
		* @param int $start The start of the recordset
		* @param int $count The number of records
		* @param string $sort The field to sort by
		*
		* @return Resource
		*/	
		function readForManageTable($start,$count,$sort="",$direction="a") {
			parent::setupDatabase();
			
			if ($direction == "a") {
				$direction = "ASC";
			} else if ($direction == "d") {
				$direction = "DESC";
			} else {
				$direction = "ASC";
			}
	
			$allowableSortFields = array("customfieldid","name","type");
			
			//Only allow certain sorting fields.
			if (!in_array($sort,$allowableSortFields)) {
				$sort = "customfieldid";
			}
			
			$preQuery = 
			"  SELECT cf.customfieldid, cf.name, cf.type "
			." FROM ".$GLOBALS['tablePrefix']."customfields cf"
			." ORDER BY ".$sort." ".$direction;
			$preQuery .= $GLOBALS['AKB_DB']->AddLimit((int)$start, (int)$count);
			
			$preResult = $GLOBALS['AKB_DB']->Query($preQuery);

			if ($GLOBALS['AKB_DB']->CountResult($preQuery)) {
				$queryArray = array();
				while ($row = $GLOBALS['AKB_DB']->Fetch($preResult)) {
					$dataConcatArray = array();
					$dataQuery = 
					"SELECT data \n"
					."FROM ".$GLOBALS['tablePrefix']."customfields_data\n"
					."WHERE customfieldid = '".trim($row['customfieldid'])."'"
					;
					$dataResult = $GLOBALS['AKB_DB']->Query($dataQuery);
					
					if ($GLOBALS['AKB_DB']->CountResult($dataQuery)) {
						while ($dataRow = $GLOBALS['AKB_DB']->Fetch($dataResult)) {
							$dataConcatArray[] = $dataRow['data'];
						}
					}
					$dataConcat = implode(', ', $dataConcatArray);
					$queryArray[] = "select cf.customfieldid, cf.name, cf.type, '$dataConcat' as data_concat FROM ".$GLOBALS['tablePrefix']."customfields cf WHERE cf.customfieldid = '".trim($row['customfieldid'])."'";
				}
				$query = implode(' UNION ', $queryArray);
				$query .= " ORDER BY ".$sort." ".$direction;
				return $this->db->Query($query);
			}
			return $preResult;
		}
		
		/**
		* readForManageTableQuery
		* Performs the same as readForManageTable but returns the count query only.
		*
		* @type static
		*
		* @return String
		*/		
		function readForManageTableCountQuery() {
			parent::setupDatabase();

			$query = "
				SELECT 
					COUNT(cf.customfieldid) as thecount
				FROM 
					".$GLOBALS['tablePrefix']."customfields cf
			";

			return $query;			
		}
		
		/**
		* readAllByQuestionID
		* Reads all customfields into an object array by the question id
		*
		* @type static
		* @param int $id The id of the customfield
		* @param bool $getData 
		*
		* @return API_CUSTOMFIELDS object
		*/		
		function readAllByQuestionID($id) {
			
			parent::setupDatabase();

			$query = "
				SELECT 
					cf.*,
					cfq.questionid,
					cfq.data
				FROM
					".$GLOBALS['tablePrefix']."customfields cf LEFT JOIN ".$GLOBALS['tablePrefix']."questions_customfields cfq ON (cf.customfieldid = cfq.customfieldid)
				WHERE
					cfq.questionid = '".$this->db->Quote($id)."'
				ORDER BY cfq.data ASC
			";
			
			$result = $this->db->Query($query);
			
			return API_CUSTOMFIELD::populateCustomFieldObjs($result);
		}
		
		/**
		* populateCustomFieldObjs
		* 
		*
		* @type static
		* @param int $id The id of the customfield
		* @param bool $getData 
		*
		* @return API_CUSTOMFIELDS object
		*/		
		function populateCustomFieldObjs($recordSet) {
			//Build the customfields and customfield data object array
			$cfObjArray = array();
			while ($tempRow = $this->db->fetch($recordSet)) {
				
				if (!isset($cfObjArray[$tempRow['customfieldid']])) {
					$tempCFObj = new API_CUSTOMFIELD();
					
					foreach ($tempCFObj->fields as $field) {
						$tempCFObj->$field = $tempRow[$field];
					}					
					
					$cfObjArray[$tempRow['customfieldid']] = $tempCFObj;
				}
				
				$tempCFDataObj = new API_CUSTOMFIELDS_DATA();
				
				if (isset($tempRow['questionid'])) {
					$tempCFDataObj->questionid = $tempRow['questionid'];
				}
				
				if (isset($tempRow['customfield_dataid'])) {
					$tempCFDataObj->customfield_dataid = (int)$tempRow['customfield_dataid'];
				}
				
				$tempCFDataObj->data = $tempRow['data'];
				$tempCFDataObj->customfieldid = $tempRow['customfieldid'];
				
				$cfObjArray[$tempRow['customfieldid']]->customFieldDataArray[] = $tempCFDataObj;
			}
			
			return $cfObjArray;
		}
		
		function deleteQuestionLinks() {
			//Check that everything is loaded.
			if (!$this->loaded) {
				$this->error = GetLang('apiNotLoaded');
				return false;
			}
			
			$query = "
				DELETE
				FROM
					".$GLOBALS['tablePrefix']."questions_customfields
				WHERE
					customfieldid = '".(int)$this->customfieldid."'
			";
			
			return $this->db->Query($query);
		}
		
		function deleteQuestionLinksByQuestion($questionid) {
			$query = "
				DELETE
				FROM
					".$GLOBALS['tablePrefix']."questions_customfields
				WHERE
					questionid = '".(int)$questionid."'
			";
			
			return $this->db->Query($query);
		}		
		
		function addQuestionLink($questionid,$data) {
			//Check that everything is loaded.
			if (!$this->loaded) {
				$this->error = GetLang('apiNotLoaded');
				return false;
			}
			
			$query = "
				INSERT INTO ".$GLOBALS['tablePrefix']."questions_customfields (
					questionid,
					customfieldid,
					data
				) VALUES (
					'".(int)$questionid."',
					'".(int)$this->customfieldid."',
					'".$this->db->Quote($data)."'
				)
			";
			
			return $this->db->Query($query);
		}
		
		function updateCustomFieldQuestionData($customfieldid,$existingDataArray) {
			//Check that everything is loaded.
			if (!$this->loaded) {
				$this->error = GetLang('apiNotLoaded');
				return false;
			}
			if (is_array($existingDataArray)) {
				foreach ($existingDataArray as $key=>$val) {
					if (trim($key) != trim($val)) {
						$query = "
							UPDATE ".$GLOBALS['tablePrefix']."questions_customfields 
							SET
								data='".$this->db->Quote($val)."'
							WHERE
								data='".$this->db->Quote($key)."'
								AND
								customfieldid = '".$this->db->Quote($customfieldid)."'
						";
						
						$this->db->Query($query);
					}
				}
			}
			
			return true;
		}
		
		function deleteCustomFieldQuestionData($customfieldid,$deleteArray) {
			//Check that everything is loaded.
			if (!$this->loaded) {
				$this->error = GetLang('apiNotLoaded');
				return false;
			}
			
			if ($deleteArray) {
				foreach ($deleteArray as $key=>$val) {
					$query = "
						DELETE FROM ".$GLOBALS['tablePrefix']."questions_customfields
						WHERE
							data='".$this->db->Quote($key)."'
							AND
							customfieldid = '".$this->db->Quote($customfieldid)."'
					";
					
					$this->db->Query($query);
				}
			}
			
			return true;
		}		
		
		/**
		* validate_name
		*
		* Make sure the name isn't blank or too long
		*
		* @param string $var
		*
		* @return bool
		*/
		function validate_name($var)
		{
			if (strlen($var) > 100) {
				$this->error = GetLang('apiCFNameTooLong');
				return false;
			}

			return true;
		}
		
		/**
		* validate_type
		*
		* Make sure the type is in the 'allowable' array
		*
		* @param string $var
		*
		* @return bool
		*/
		function validate_type($var)
		{
			if (!in_array($var,$this->customFieldAllowableTypes)) {
				return false;
			}

			return true;
		}
	}
	
	class API_CUSTOMFIELDS_DATA extends API {
	
		var $fields = array (
			'customfield_dataid',
			'customfieldid',
			'data'
		);

		var $pk = 'customfield_dataid';
		
		var $customfield_dataid = 0;
		var $customfieldid = 0;
		var $data = 0;
		
		function API_CUSTOMFIELDS_DATA($id=false) {
			parent::API();
			
			$this->table = $GLOBALS['tablePrefix']."customfields_data";
			
			if ((int)$id > 0) {
				parent::read();
			}			
		}
		
		/**
		* Create a new item in the database
		*
		* @return mixed false if failed to create, the id of the item otherwise
		*/
		function create()
		{
			return parent::create();
		}
		
		/**
		* save
		* save the custom field back to the database
		*
		* @return bool was the save successful ?
		*/
		function save()
		{
			return parent::save();
		}

		/**
		* delete
		* Delete a custom field, delete any data it may contain and any question links it may have.
		*
		* @param int $id The id of the category to delete
		*
		* @return bool Was the delete successful ?
		*/
		function delete($id=0)
		{
			return parent::delete();
		}
		
		/**
		* delete
		* Delete a custom field, delete any data it may contain and any question links it may have.
		*
		* @param int $id The id of the category to delete
		*
		* @return bool Was the delete successful ?
		*/
		function deleteByCustomFieldID($cfid) {
			
			$query = "
				DELETE FROM
					".$GLOBALS['tablePrefix']."customfields_data
				WHERE
					customfieldid = '".(int)$cfid."'
			";
			
			$result = $this->db->Query($query);
		}		
	}
	
	/**
	* custom_fields_helper
	*
	* Because alot of these custom fields objects rely on each other.
	* this static class is for all common kinds of things.
	*
	*/
	class custom_fields_helper {
	
		/**
		* get_all_custom_fields
		*
		* Returns all custom fields as a custom field object array
		*
		* return array (of CUSTOMFIELD objects)
		*/
		function get_all_custom_fields() {
			return API_CUSTOMFIELD::readAll();
		}
		
		/**
		* get_custom_fields_by_question
		*
		* Returns all custom fields as a custom field object array
		*
		* return array (of CUSTOMFIELD objects)
		*/
		function get_custom_fields_by_question($questionid) {
			return API_CUSTOMFIELD::readAllByQuestionID($questionid);
		}
		
		/**
		* derive_cf_multi_string
		*
		* Takes a custom field data object array and concatenates togethor for display in the UI. 
		*
		* @static
		* @param $cfDataObjArray An array of custom field data objects.
		*
		* return string
		*/
		function derive_cf_multi_string($cfDataObjArray) {
			$derString = "";
			
			if (is_array($cfDataObjArray)) {
				foreach ($cfDataObjArray as $cfDataObj) {
					$derString .= $cfDataObj->data."\n";
				}
			}
			
			return $derString;
		}
		
		/**
		* process_cf_multi_string
		*
		* Takes a string from the UI and seperates into a custom field object array ready for insert into the database (opposite of above).
		*
		* @static
		* @param $cfDataObjArray An array of custom field data objects.
		*
		* return string
		*/		
		function process_cf_multi_string($uiString,$customfieldid,$simpleArray=false) {
		
			$tempStrArray = explode("\n",$uiString);
			
			$tempObjArray = array();
			foreach ($tempStrArray as $dataStr) {
				if (trim($dataStr) != "") {
					if ($simpleArray) {
						$tempObjArray[] = trim($dataStr);
					} else {
						$cfDataObjTemp = new API_CUSTOMFIELDS_DATA();
						$cfDataObjTemp->usePostVars = false;
						$cfDataObjTemp->customfieldid = $customfieldid;
						$cfDataObjTemp->data = trim($dataStr);

						$tempObjArray[] = $cfDataObjTemp;
					}
				}
			}
			
			return $tempObjArray;
		}
		
		/**
		* create_custom_field 
		*
		* @param name
		*
		*/
		function create_custom_field($name,$type,$customfield_string) {
			//Create the customfield.
			$cfObj = new API_CUSTOMFIELD();
			$cfObj->name = $name;
			$cfObj->type = $type;
			$successId = $cfObj->create();
			
			if (!$successId) {
				return false;
			}
			
			//Derive the data objects from the UI string
			$custom_fields_data_obj_array = custom_fields_helper::process_cf_multi_string($customfield_string,$cfObj->customfieldid);
			
			if ($type != CF_TYPE__FREE_FORM) {
				//Derive the data objects from the UI string
				$custom_fields_data_obj_array = custom_fields_helper::process_cf_multi_string($customfield_string,$successId);			
			
				//Insert all of the custom field data objects
				return custom_fields_helper::process_insert_cfdata_objects($custom_fields_data_obj_array);
			}
			
			return true;
		}
		
		function update_custom_field($customfieldid,$name,$type,$customfield_string,$updateArray,$deleteArray) {
			//Update the actual object data.
			$cfobj = new API_CUSTOMFIELD($customfieldid,true);
			$cfobj->name = $name;
			$cfobj->type = $type;
			$cfobj->usePostVars = false;
			if (!$cfobj->save()) {
				return $cfobj->error;
			}
			
			$cfobj->updateCustomFieldQuestionData($customfieldid,$updateArray);
			$cfobj->deleteCustomFieldQuestionData($customfieldid,$deleteArray);
			
			custom_fields_helper::delete_cfdata_objects($cfobj->customFieldDataArray,$customfieldid);
			
			if ($type != CF_TYPE__FREE_FORM) {
				//Derive the data objects from the UI string
				//First we tack the updated ones to the end.
				if (!is_array($updateArray)) {
					$updateArray = array();
				}
				$customfield_string = $customfield_string."\n".implode("\n", $updateArray);
				
				//Now process the string
				$custom_fields_data_obj_array = custom_fields_helper::process_cf_multi_string($customfield_string,$customfieldid);
				
				//Insert all of the custom field data objects
				return custom_fields_helper::process_insert_cfdata_objects($custom_fields_data_obj_array);
			}
			return true;
		}
		
		function process_insert_cfdata_objects($custom_fields_data_array) {
			//Now create the optional data to go along with this.
			if ((is_array($custom_fields_data_array)) && (count($custom_fields_data_array) > 0)) {
				foreach ($custom_fields_data_array as $cfDataObj) {
					$cfDataObj->create();
				}
			} else {
				return false;
			}
			
			return true;
		}
		
		function delete_custom_field($customfieldid) {
			//Load the object
			$cfObj = new API_CUSTOMFIELD($customfieldid,true);
			
			//Delete all question links
			$cfObj->deleteQuestionLinks();
			
			//Delete all custom field data objects
			custom_fields_helper::delete_cfdata_objects($cfObj->customFieldDataArray,$customfieldid);
			
			//Delete the customfield object
			return $cfObj->delete($customfieldid);
		}
		
		function delete_cfdata_objects($cfDataObjArray,$customfieldid) {
			//Loop through data objects and delete all
			foreach ($cfDataObjArray as $cfDataObj) {
				$cfDataObj->deleteByCustomFieldID($customfieldid);
			}
			
			return true;
		}
	}

?>