<?php
/*
Officity - Web application platform - Version 6.0 - 2011-07-05

François Dispaux, Boris Verdeyen, Thomas Hermant,
Jérémie Roy, Grégory Meurice, Abdelila Harbi, 
Marc Mignonsin, Jonathan Sanchez, Julien Gonzalez, Pierre Fouchez

Sushee and Officity is © Copyright 2011 Nectil SA.

`/sushee-source/sushee/private/delete.inc.php` is part of Officity.

Sushee is free software: 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 3 of the License, or
(at your option) any later version.

Officity and Sushee are distributed in the hope that they will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with Sushee. If not, see <http://www.gnu.org/licenses/>.
*/
require_once(dirname(__FILE__).'/../common/nqlOperation.class.php');
require_once(dirname(__FILE__)."/../common/dependencies.class.php");
require_once(dirname(__FILE__)."/../common/descriptions.class.php");
require_once(dirname(__FILE__)."/../common/nectil_element.class.php");
require_once(dirname(__FILE__)."/../common/nectil_user.class.php");
require_once(dirname(__FILE__)."/../common/descriptions.inc.php");
require_once(dirname(__FILE__)."/../common/dependencies.inc.php");
require_once(dirname(__FILE__)."/../common/categories.inc.php");
require_once(dirname(__FILE__)."/../common/properties.inc.php");
require_once(dirname(__FILE__)."/../common/log.class.php");
require_once(dirname(__FILE__)."/../private/metaSearch.inc.php");

class deleteElement extends NQLOperation{
	var $moduleInfo = false;
	var $elementIDs = array();
	var $force = false;
	
	function parse(){
		$this->logFunction('deleteElement.parse');
		$moduleName  = $this->firstNode->nodeName();
		$moduleInfo = moduleInfo($moduleName);
		if ($moduleInfo->loaded==FALSE){
			$this->setError("The informations about the module $moduleName couldn't be found.");
			return false;
		}
		$force = $this->operationNode->getAttribute('force');
		if($force==='true'){
			$this->force = true;
		}
		
		$this->moduleInfo = $moduleInfo;
		return true;
	}
	
	function operate(){
		$this->logFunction('deleteElement.operate');
		$db_conn = db_connect();
		$moduleInfo = $this->moduleInfo;
		$xml = $this->firstNode->getDocument();
		$current_path = $this->operationNode->getPath();
		$firstNodePath = $this->firstNode->getPath();
		$firstNode = $this->firstNode->nodeName();
		$requestName = $this->operationNode->nodeName();
		$name = $this->name;
		$IDs_string = $this->firstNode->valueOf("@ID");
		
		if ($IDs_string==FALSE){
			// trying to find a WHERE node : deleting multiple elements matching what is inside the WHERE node
			$where_node = $this->firstNode->getElement("WHERE[1]");
			if( $where_node ){
				
				
				// composing a smaller XML with only a SEARCH command with the content of the WHERE
				$small_xml = new XML(
					'<SEARCH><'.$firstNode.'>'.$where_node->toString().'</'.$firstNode.'><RETURN><NOTHING/></RETURN></SEARCH>');
				// we apply preprocessing to have the extension boolean added
				$preprocess = $moduleInfo->preProcess('SEARCH',false,$small_xml->getElement('/SEARCH'),$former_values,$new_values,$return_values);	
					
				$where_sql = "";
				$where_rs = getResultSet($moduleInfo,$small_xml,'/SEARCH[1]',$where_sql);
				// the SQL request in order to resolve the WHERE failed : we return the error to the user
				if (is_string($where_rs)){
					$this->setError($where_rs);
					return false;
				}
					
				if (!$where_rs){
					$this->setError($db_conn->ErrorMsg().$where_sql);
					return false;
				}
				
				// we have the elements IDs, checking all of them can be deleted (no locked or private elements)
				$first = true;
				while($search_row = $where_rs->FetchRow()){
					$res = $this->checkElement($search_row['ID']);
					if(!$res){
						return false;
					}
					$first = false;
				}
				$where_rs->MoveFirst();
				while($search_row = $where_rs->FetchRow()){
					$this->operateElement($search_row['ID']);
				}
				if ($first==true){
					$this->setError("The search hasn't given any result -> no deletion has been processed.",4);
					return false;
				}
					
			}else{
				$this->setError("No ID was set -> no deletion has been processed.");
				return false;
			}
		}else{
			$IDs_array = explode(",",$IDs_string);
			foreach($IDs_array as $ID){
				$res = $this->checkElement($ID);
				if(!$res){
					return false;
				}
			}
			foreach($IDs_array as $ID){
				$this->operateElement($ID);
			}
		}
		$this->setSuccess('Delete successfully processed.');
		return true;
	}
	
	function checkElement($ID){
		$this->logFunction('checkElement.operateElement '.$ID);
		$db_conn = db_connect();
		$moduleInfo = $this->moduleInfo;
		$xml = $this->firstNode->getDocument();
		$current_path = $this->operationNode->getPath();
		$firstNodePath = $this->firstNode->getPath();
		$firstNode = $this->firstNode->nodeName();
		$requestName = $this->operationNode->nodeName();
		
		$IDs_array[0] = $ID; // for compatibility !!!
		$user = new NectilUser();
		$userID = $user->getID();
		
		$values = getInfo($moduleInfo,$ID);
		
		// ------------------------------------------------------------------------
		// PREPROCESSING
		// ------------------------------------------------------------------------
		$nativeModule = $moduleInfo->getParentModule();
		
		$new_values = array();
		$this->preprocess = $preprocess = $moduleInfo->preProcess($requestName,$ID,$this->operationNode,$values,$new_values,$return_values);
		// processors can send errors. If there is an error, we stop the update and return the error message
		if($preprocess->containsError()){
			$error = $preprocess->getError();
			$this->setError($error->getMessage(),$error->getCode());
			return false;
		}
		// ------------------------------------------------------------------------
		// SECURITY CHECKS
		// ------------------------------------------------------------------------
		
		// we forbid the delete of the native contacts of nectil employees
		if( !$this->force && ($moduleInfo->name=='contact' && $userID==$ID && $userID!=1857 && $userID!=3334) ){
			$this->setSecurityError('You can\'t erase your own contact : you wouldn\'t be able to connect to Officity anymore.');
			return false;
		}
			
		// verifying delete is autorized for the user 
		if(!$moduleInfo->getActionSecurity('DELETE',$values)){
			$this->setSecurityError("You're not authorized to delete elements of this module (ID:".$ID.").");
			return false;
		}
		// locked elements are elements that cannot be deleted
		if( !$this->force && $values['IsLocked']==1){
			$this->setSecurityError('This element (ID:'.$ID.') is locked : it cannot been deleted.');
			return false;
		}
		// private element cannot be deleted unless the user is the owner (valid only if user is limited to private elements)
		if($moduleInfo->IsPrivacySensitive){
			if(!$moduleInfo->isElementAuthorized($values,'W')){
				$this->setSecurityError("You're not authorized to delete this element (ID:$ID) (you didn't create it and  it doesn't belong to your team).");
				return false;
			}
		}
		// forbidding to delete element if they still have dependencies (KILL is not limited by this behaviour)
		if ($requestName!=='KILL'){
			$linked = hasTypedLinks($moduleInfo->ID,$ID);
			if ($linked){
				$this->setSecurityError('This element (ID:'.$ID.') is linked to another element. Try to destroy it instead.');
				return false;
			}
		}
			
		
		return true;
	}
	
	function operateElement($ID){
		$this->logFunction('deleteElement.operateElement '.$ID);
		$db_conn = db_connect();
		$moduleInfo = $this->moduleInfo;
		$xml = $this->firstNode->getDocument();
		$current_path = $this->operationNode->getPath();
		$firstNodePath = $this->firstNode->getPath();
		$firstNode = $this->firstNode->nodeName();
		$requestName = $this->operationNode->nodeName();
		$IDs_array[0] = $ID; // for compatibility !!!
		// ------------------------------------------------------------------------
		// SERVICES MANAGEMENT : DEPENDENCIES, CATEGORIES, DESCRIPTIONS, PROPERTIES
		// ------------------------------------------------------------------------
		// dependencies
		// dependencies are deleted anyway, even if its an extension, because extension have their own dependencytype
		$othersql.=deleteDependenciesTo($moduleInfo->ID,$ID);
		$othersql.=deleteDependenciesFrom($moduleInfo->ID,$ID);
		
		// other services are deleted only on the native module
		if(!$moduleInfo->isExtension()){
			//categories
			$othersql.=removeFromCategories($moduleInfo->ID,$ID);
			//descriptions
			$othersql.=deleteDescriptions($moduleInfo->ID,$ID);
			// comments
			$othersql.=deleteComments($moduleInfo->ID,$ID);
			// properties
			$othersql.=deleteProperties($moduleInfo->ID,$ID);
			// omnilinks
			$destructor = new sushee_omnilinksDestructor($moduleInfo,$ID);
			$destructor->execute();
		}
		
		
		// ------------------------------------------------------------------------
		// SQL TREATMENT
		// ------------------------------------------------------------------------
		$sql = "";
		// generating the condition with the entry Ids to disable or delete
		$IDs_condition = " WHERE ";
		$IDs_condition.='`ID` = \''.$ID.'\'';
		// final sql query is :
		if($moduleInfo->getName()=='resident' && $GLOBALS["NectilMasterURL"]!='nectil.com'){
			$real_delete = TRUE;
		}
		if($moduleInfo->getName()=='module' || $moduleInfo->getName()=='field'){
			$real_delete = TRUE;
		}
		if ( $real_delete == TRUE ){
		   $sql = 'DELETE FROM `'.$moduleInfo->tableName.'` '.$IDs_condition.';';
		}else{
			$user = new NectilUser();
			$userID = $user->getID();
			if($moduleInfo->isExtension()){
				// if delete is on an extension, only disabling the element from the extension and its descending extension
				$to_disable = $moduleInfo->getExtensions();
				$disabling_sql = '`'.$moduleInfo->getName().'` = 0,';
				while($disabled  = $to_disable->next()){
					$disabling_sql.= '`'.$disabled->getName().'` = 0,';
				}
				$sql = 'UPDATE `'.$moduleInfo->tableName.'` SET '.$disabling_sql.' `ModificationDate` = "'.$GLOBALS['sushee_today'].'",`ModifierID`=\''.$userID.'\' '.$IDs_condition.';';
			}else{
				if($moduleInfo->name=='mail'){
					$sql = 'UPDATE `'.$moduleInfo->tableName.'` SET `Activity`=0,`ModificationDate`="'.$GLOBALS['sushee_today'].'",`From`="",`RichText`="",`StyledText`="",`PlainText`="",`Subject`="",`To`="",`Cc`="",`Folder`="",`Attachments`="",`SearchText`="" '.$IDs_condition.';';
				}else{
					$sql = 'UPDATE `'.$moduleInfo->tableName.'` SET `Activity`=0,`ModificationDate`="'.$GLOBALS['sushee_today'].'",`ModifierID`=\''.$userID.'\' '.$IDs_condition.';';
				}
			}
		}
		$this->logSQL($sql);
		$db_conn->Execute($sql);
		
		// ------------------------------------------------------------------------
		// ACTION LOGGING
		// ------------------------------------------------------------------------
		$action_log_file = new UserActionLogFile();
		$action_object = new UserActionObject($moduleInfo->getName(),$ID);
		$action_log = new UserActionLog($this->getOperation(), $action_object );
		$action_log_file->log( $action_log );
		// ------------------------------------------------------------------------
		// POSTPROCESSING
		// ------------------------------------------------------------------------
		$nativeModule = $moduleInfo->getParentModule();

		$this->postprocess = $moduleInfo->postProcess($requestName,$ID,$this->operationNode,$former_values,$values,$return_values);

		if ($nativeModule && file_exists(dirname(__FILE__)."/../private/".$nativeModule->getName()."_fileprocessing.php") )
			include(dirname(__FILE__)."/../private/".$nativeModule->getName()."_fileprocessing.php");
		else
			include(dirname(__FILE__)."/../private/general_fileprocessing.php");
		$this->elementIDs[]=$ID;
		return true;
	}
	
	function setSuccess($msg){
		$attributes = $this->getOperationAttributes();
		$this->msg = "<MESSAGE".$attributes." msgType=\"0\" hits=\"".sizeof($this->elementIDs)."\" elementID=\"".implode(',',$this->elementIDs)."\">".encode_to_xml($msg).$this->preprocess->getXML().$this->postprocess->getXML()."</MESSAGE>";
	}
}
?>
