<?php
	/**
	 * RestoreItemsList Module
	 */
	class RestoreItemsListModule extends ListModule
	{
		/**
		 * Constructor
		 * @param int $id unique id.
		 * @param array $data list of all actions.
		 */
		function RestoreItemsListModule($id, $data)
		{
			parent::ListModule($id, $data);// array(OBJECT_SAVE, TABLE_SAVE, TABLE_DELETE));
			$this->start = 0;
		}
		
		
		/**
		 * Executes all the actions in the $data variable.
		 * @return boolean true on success of false on failure.
		 */
		function execute()
		{
			foreach($this->data as $actionType => $action)
			{
				if(isset($actionType)) {
					try {
						$store = $this->getActionStore($action);
						$parententryid = $this->getActionParentEntryID($action);
						$folderentryid = $this->getActionEntryID($action);
						//using regular expression we find action type and accordingly assigns the properties 
						$this->properties = (strpos($actionType, "folder") !== false)? $GLOBALS["properties"]->getFolderProperties() : $GLOBALS["properties"]->getMailProperties();
						
						if($actionType != "list" && $actionType != "folderlist"){	
							$entrylist = array();
							if(isset($action["folders"])){
								//checks for the entryid tag when a client sends a response for restore or delete of folder. 
								if(isset($action["folders"]["folder"]) && isset($action["folders"]["folder"]["entryid"])) {
									array_push($entrylist, $action["folders"]["folder"]);
								}else {
										foreach($action["folders"]["folder"] as $key => $value) {
										array_push($entrylist, $action["folders"]["folder"][$key]);
									}
								}
							}else{
								if(isset($action["messages"]["message"]) && isset($action["messages"]["message"]["entryid"])) {
									array_push($entrylist, $action["messages"]["message"]);
								}else {
										foreach($action["messages"]["message"] as $key => $value) {
										array_push($entrylist, $action["messages"]["message"][$key]);
									}
								}
							}	
						}

						switch($actionType) {
							case "list":
								$this->messageList($store, $folderentryid, $action, $actionType);
								break;
							
							case "deleteallmsg":
								$this->deleteAll($store, $folderentryid, $action);
								break;

							case "restoreallmsg":
								$this->restoreAll($store, $folderentryid, $action);
								break;
							
							case "deletemsg":
								$this->deleteItems($store, $folderentryid, $entrylist, $action);
								break;

							case "restoremsg":
								$this->restoreItems($store, $folderentryid, $entrylist, $action);
								break;

							case "folderlist":
								$this->folderList($store, $folderentryid, $action);
								break;

							case "deleteallfolder":
								$this->deleteAllFolder($store, $folderentryid, $action);
								break;

							case "restoreallfolder":
								$this->restoreAllFolder($store, $folderentryid, $action);
								break;

							case "deletefolder":
								$this->deleteFolder($store, $folderentryid, $entrylist, $action);
								break;

							case "restorefolder":
								$this->restoreFolder($store, $folderentryid, $entrylist, $action);
								break;

							default:
								$this->handleUnknownActionType($actionType);
						}

						// check if $actionType is other then list/folderlist and 
						// return of action is true then call the new list of items to be sent to the client back.
						switch($actionType)	{
							case "deletemsg":
							case "deleteallmsg":
							case "restoremsg":
							case "restoreallmsg":
								$this->messageList($store, $folderentryid, $action, $actionType);
								break;
							
							case "deletefolder":
							case "deleteallfolder":
							case "restorefolder":
							case "restoreallfolder":
								$this->folderList($store, $folderentryid, $action);
								break;
							default:
								break;
						}
					} catch (MAPIException $e) {
						$this->processException($e, $actionType);
					}
				}
			}
		}

		/**
		 * Function to retrieve the list of items of particular folder's entry id
		 * @param object $store store object.
		 * @param binary $entryid entry id of that particular folder.
		 * @param object $action request data.
		 * @param string $actionType the action type, sent by the client
		 * return - true if result is successful.
		 */
		function messageList($store, $entryid, $action, $actionType){
			
			//set the this->$sort variable.
			$this->parseSortOrder($action);

			$data = array();

			$folder = mapi_msgstore_openentry($store, $entryid);
			$table = mapi_folder_getcontentstable($folder, MAPI_DEFERRED_ERRORS | SHOW_SOFT_DELETES);
			
			//sort the table according to sort data
			if (is_array($this->sort) && !empty($this->sort)){
				mapi_table_sort($table, $this->sort, TBL_BATCH);
			}
			$restoreitems = mapi_table_queryallrows($table, Array(PR_ENTRYID, PR_MESSAGE_CLASS, PR_SUBJECT, PR_SENDER_NAME, PR_DELETED_ON, PR_MESSAGE_SIZE ));
			$items = Array();
			foreach($restoreitems as $restoreitem)
			{
				$item = null;
				$item = Conversion::mapMAPI2XML($this->properties, $restoreitem);
				array_push($items,$item);
			} 
			$data["item"] = $items;

			$this->addActionData("list", $data);
			$GLOBALS["bus"]->addData($this->getResponseData());

			return true;
		}
		
		/**
		 * Function to delete all items of particular folder's entry id
		 * @param object $store store object.
		 * @param binary $folderentryid entry id of that particular folder.
		 * @param object $action request data.
		 * return - true if result is successful.
		 */

		function deleteAll($store, $folderentryid, $action){
			$entrylist = Array();
			$folder = mapi_msgstore_openentry($store, $folderentryid);
			$table = mapi_folder_getcontentstable($folder, MAPI_DEFERRED_ERRORS | SHOW_SOFT_DELETES);
			$rows = mapi_table_queryallrows($table, array(PR_ENTRYID));
			for($i = 0, $len = count($rows); $i < $len; $i++){
				array_push($entrylist, $rows[$i][PR_ENTRYID]);
			}
			mapi_folder_deletemessages($folder, $entrylist, DELETE_HARD_DELETE);
		}

		/**
		 * Function to restore all items of particular folder's entry id
		 * @param object $store store object.
		 * @param binary $folderentryid entry id of that particular folder.
		 * @param object $action request data.
		 * return - true if result is successful.
		 */
		function restoreAll($store, $folderentryid, $action){
			$entryidlist = Array();
			$sfolder = mapi_msgstore_openentry($store, $folderentryid);
			$table = mapi_folder_getcontentstable($sfolder, MAPI_DEFERRED_ERRORS | SHOW_SOFT_DELETES);
			$rows = mapi_table_queryallrows($table, array(PR_ENTRYID));
			for($i = 0, $len = count($rows); $i < $len; $i++){
				array_push($entryidlist, $rows[$i][PR_ENTRYID]);
			}
			mapi_folder_copymessages($sfolder, $entryidlist, $sfolder, MESSAGE_MOVE);

			// as after moving the message/s the entryid gets changed, so need to notify about the folder
			// so that we can update the folder on parent page.
			$folderProps = mapi_getprops($sfolder, array(PR_ENTRYID, PR_STORE_ENTRYID, PR_PARENT_ENTRYID));
			$GLOBALS["bus"]->notify(bin2hex($folderentryid), TABLE_SAVE, $folderProps);
		}

		/**
		 * Function to delete selected items of particular folder
		 * @param object $store store object.
		 * @param binary $folderentryid entry id of that particular folder.
		 * @param array $entryidlist array of entry ids of messages to be deleted permanently
		 * @param object $action request data.
		 * return - true if result is successful.
		 */
		function deleteItems($store, $folderentryid, $entryidlist, $action){
			$binEntryIdList = Array();

			foreach($entryidlist as $key => $value){
				$binEntryIdList[] = hex2bin($entryidlist[$key]["entryid"]);
			}
			
			$sfolder = mapi_msgstore_openentry($store, $folderentryid);
			mapi_folder_deletemessages($sfolder, $binEntryIdList, DELETE_HARD_DELETE);
		}
		
		/**
		 * Function to restore selected folder
		 * @param object $store store object.
		 * @param binary $folderentryid entry id of that particular folder.
		 * @param array $entryidlist array of entry ids of messages to be deleted permanently
		 * @param object $action request data.
		 * return - true if result is successful.
		 */
		function restoreItems($store, $folderentryid, $entryidlist, $action){
			$binEntryIdList = Array();
			
			foreach($entryidlist as $key => $value){
				$binEntryIdList[] = hex2bin($entryidlist[$key]["entryid"]);
			}

			$sfolder = mapi_msgstore_openentry($store, $folderentryid);
			mapi_folder_copymessages($sfolder, $binEntryIdList, $sfolder, MESSAGE_MOVE);

			// as after moving the message/s the entryid gets changed, so need to notify about the folder
			// so that we can update the folder on parent page.
			$folderProps = mapi_getprops($sfolder, array(PR_ENTRYID, PR_STORE_ENTRYID, PR_PARENT_ENTRYID));
			$GLOBALS["bus"]->notify(bin2hex($folderentryid), TABLE_SAVE, $folderProps);
		}

		/**
		 * Function to retrieve the list of folders of particular folder's entry id
		 * @param object $store store object.
		 * @param binary $entryid entry id of that particular folder.
		 * @param object $action request data.
		 * return - true if result is successful.
		 */
		function folderList($store, $entryid, $action){	

			//set the this->$sort variable.
			$this->parseSortOrder($action);

			$data = array();
			
			$folder = mapi_msgstore_openentry($store, $entryid);
			$table = mapi_folder_gethierarchytable($folder, MAPI_DEFERRED_ERRORS | SHOW_SOFT_DELETES);			
			
			//sort the table according to sort data
			if (is_array($this->sort) && !empty($this->sort)){
				mapi_table_sort($table, $this->sort, TBL_BATCH);
			}
			$restoreitems = mapi_table_queryallrows($table, Array(PR_ENTRYID, PR_DISPLAY_NAME, PR_DELETED_ON, PR_CONTENT_COUNT));
			$items = Array();
			foreach($restoreitems as $restoreitem){
				$item = Conversion::mapMAPI2XML($this->properties, $restoreitem);
				array_push($items,$item);
			} 
			$data["item"] = $items;
	
			$this->addActionData("folderlist", $data);
			$GLOBALS["bus"]->addData($this->getResponseData());

			return true;
		}	
	
		/**
		 * Function to delete all folders of particular
		 * @param object $store store object.
		 * @param binary $folderentryid entry id of that particular folder.
		 * @param object $action request data.
		 * return - true if result is successful.
		 */
		function deleteAllFolder($store, $folderentryid, $action){
			$folder = mapi_msgstore_openentry($store, $folderentryid);
			$table = mapi_folder_gethierarchytable($folder, MAPI_DEFERRED_ERRORS | SHOW_SOFT_DELETES);
			$rows = mapi_table_queryallrows($table, array(PR_ENTRYID));
			for($i = 0, $len = count($rows); $i < $len; $i++){
				mapi_folder_deletefolder($folder, $rows[$i][PR_ENTRYID], DEL_FOLDERS | DEL_MESSAGES | DELETE_HARD_DELETE);
			}
		}

		/**
		 * Function to restore all folders of particular
		 * @param object $store store object.
		 * @param binary $folderentryid entry id of that particular folder.
		 * @param object $action request data.
		 * return - true if result is successful.
		 */
		function restoreAllFolder($store, $folderentryid, $action){
			$sfolder = mapi_msgstore_openentry($store, $folderentryid);
			$table = mapi_folder_gethierarchytable($sfolder, MAPI_DEFERRED_ERRORS | SHOW_SOFT_DELETES);
			$rows = mapi_table_queryallrows($table, array(PR_ENTRYID, PR_DISPLAY_NAME));	
			for($i = 0, $len = count($rows); $i < $len; $i++){
				//checks for conflicting folder name before restoring the selected folder,
				//if names conflict a postfix of integer is add to folder name else nochange. 
				$foldername = $GLOBALS["operations"]->checkFolderNameConflict($store, $sfolder, $rows[$i][PR_DISPLAY_NAME]);
				mapi_folder_copyfolder($sfolder, $rows[$i][PR_ENTRYID], $sfolder, $foldername, FOLDER_MOVE);	
			}

			// as after moving the folder/s the entryid gets changed, so need to notify about the folder
			// so that we can update the folder on parent page.
			$folderProps = mapi_getprops($sfolder, array(PR_ENTRYID, PR_STORE_ENTRYID, PR_PARENT_ENTRYID));
			$GLOBALS["bus"]->notify(bin2hex($folderentryid), TABLE_SAVE, $folderProps);
		}

		/**
		 * Function to delete selected folders
		 * @param object $store store object.
		 * @param binary $folderentryid entry id of that particular folder.
		 * @param array $entryidlist array of entry ids of folder to be deleted permanently
		 * @param object $action request data.
		 * return - true if result is successful.
		 */
		function deleteFolder($store, $folderentryid, $entryidlist, $action){
			$binEntryIdList = Array();
			
			foreach($entryidlist as $key => $value){
				$binEntryIdList[] = hex2bin($entryidlist[$key]["entryid"]);
			}
			
			$sfolder = mapi_msgstore_openentry($store, $folderentryid);

			foreach ($binEntryIdList as $key=>$folderlist){
				mapi_folder_deletefolder($sfolder, $folderlist, DEL_FOLDERS | DEL_MESSAGES | DELETE_HARD_DELETE);
			}
		}
		
		/**
		 * Function to restore selected items of particular folder
		 * @param object $store store object.
		 * @param binary $folderentryid entry id of that particular folder.
		 * @param array $entryidlist array of entry ids of folder to be deleted permanently
		 * @param object $action request data.
		 * return - true if result is successful.
		 */
		function restoreFolder($store, $folderentryid, $entryidlist, $action){	
			$binEntryIdList = Array();
			$displayNameList = Array();
			//here the entryids and displaynames are stored in seprate arrays so 
			//that folders display name can be checked for conflicting names which restoring folders. 
			foreach($entryidlist as $key => $value){
				$binEntryIdList[] = hex2bin($entryidlist[$key]["entryid"]);
				$displayNameList[] = $entryidlist[$key]["display_name"];
			}
			
			$sfolder = mapi_msgstore_openentry($store, $folderentryid);
			for($entryindex = 0, $len = count($binEntryIdList); $entryindex < $len; $entryindex++){
				mapi_folder_copyfolder($sfolder, $binEntryIdList[$entryindex], $sfolder, $displayNameList[$entryindex], FOLDER_MOVE);
				//here we check mapi errors for conflicting of names when folder/s is restored. 
				if(mapi_last_hresult()==MAPI_E_COLLISION){
					$foldername = $GLOBALS["operations"]->checkFolderNameConflict($store, $sfolder, $displayNameList[$entryindex]);
					mapi_folder_copyfolder($sfolder, $binEntryIdList[$entryindex], $sfolder, $foldername, FOLDER_MOVE);
				}
			}
			
			// as after moving the folder's the entryid gets changed, so need to notify about the folder
			// so that we can update the folder on parent page.
			$folderProps = mapi_getprops($sfolder, array(PR_ENTRYID, PR_STORE_ENTRYID, PR_PARENT_ENTRYID));
			$GLOBALS["bus"]->notify(bin2hex($folderentryid), TABLE_SAVE, $folderProps);
		}
	}
?>
