<?php

/**
 * @class support
 * @brief Manage support tickets
 * @author Xavier Perrissoud
 * @modified Benjamin Mercier
 * @date 29/04/2009
 * @version 0.1
 *
*/
class support{
	
	/**
	 * @brief Cache variable with total of tickets for the current user
	*/
	private $user_tickets = null;
	
	/**
	 * @brief Cache variable with total of tickets waiting for a support reply
	*/
	private $waiting_tickets = null;
	
	/**
	 * @brief Cache variable with total of tickets for witch the support made a reply
	*/
	private $replied_tickets = null;
	
	/**
	 * @brief Cache array with total of messages for each tickets
	*/
	private $ticket_messages = array();

	/**
	 * @brief List all tickets of a given user
	 * @param user_id -> id of the user for witch we want the tickets list (must be specified)
	 * @param start -> First ticket to extract (can be NULL)
	 * @param extract -> Number of tickets to extract (can be NULL)
	 * @return array of tickets informations (NULL if empty)
	*/
	public function getUserTickets($user_id, $start = NULL, $extract = NULL) 
	{
		$user_id = $_SESSION['database']->clearString($user_id);
		// if paging informations are given, create the LIMIT clause
		if ( !is_null($start) and !is_null($extract) ) {
			$start = $_SESSION['database']->clearString($start);
			$extract = $_SESSION['database']->clearString($extract);
			$limit = "LIMIT $start, $extract";
		} else $limit = NULL;
	
		$req = "SELECT
					t.id AS ticket_id,
					t.subject,
					UNIX_TIMESTAMP(t.open_date) AS open_date,
					t.status,
					h.base_name AS hosting_name
					FROM tickets AS t
					LEFT JOIN hostings AS h
					ON h.id = t.hosting_id
					WHERE t.user_id = '$user_id'
					ORDER BY t.open_date DESC $limit";

		$tickets_list = $_SESSION['database']->fetchObject($req);
		foreach ($tickets_list as $item) {
			$item->subject=stripslashes($item->subject);
		}

		return $tickets_list;
	} // End of getUserTickets
	
	/**
	 * @brief List all tickets of the current user
	 * @param start -> First ticket to extract (can be NULL)
	 * @param extract -> Number of tickets to extract (can be NULL)
	 * @return array of tickets informations (NULL if empty)
	*/
	public function userGetTickets($start = NULL, $extract = NULL) 
	{
		$user_id=$_SESSION['user']->information_user->userid;
		
		return $this->getUserTickets($user_id, $start, $extract);
	} // End of userGetTickets

	/**
	 * @brief List all "waiting for a reply" tickets, sorted by last message date, older in first position
	 * @param start -> First ticket to extract (can be NULL)
	 * @param extract -> Number of tickets to extract (can be NULL)
	 * @return array of tickets informations (NULL if empty)
	*/
	public function getWaitingTickets($start = NULL, $extract = NULL)
	{
		// if paging informations are given, create the LIMIT clause
		if ( !is_null($start) and !is_null($extract) ) {
			$start = $_SESSION['database']->clearString($start);
			$extract = $_SESSION['database']->clearString($extract);
			$limit = "LIMIT $start, $extract";
		} else $limit = NULL;
		
		$sql = "SELECT
					t.id AS ticket_id,
					t.subject,
					UNIX_TIMESTAMP(t.open_date) AS open_date,
					t.status,
					UNIX_TIMESTAMP(t.last_msg_date) AS last_msg_date,
					h.base_name AS hosting_name
					FROM tickets AS t
					LEFT JOIN hostings AS h
					ON h.id = t.hosting_id
					WHERE t.status = 'asked'
					ORDER BY t.last_msg_date ASC $limit";
					
		$tickets_list = $_SESSION['database']->fetchObject($sql);
		// Check if tickets list is not empty
		if ( !isset($tickets_list[0]) ) return NULL;
		
		foreach ($tickets_list as $item) {
			$item->subject=stripslashes($item->subject);
		}
		return $tickets_list;
	}
	
	/**
	 * @brief List all "replied but not closed" tickets, sorted by last message date, older in first position
	 * @param start -> First ticket to extract (can be NULL)
	 * @param extract -> Number of tickets to extract (can be NULL)
	 * @return array of tickets informations (NULL if empty)
	*/
	public function getRepliedTickets($start = NULL, $extract = NULL)
	{
		// if paging informations are given, create the LIMIT clause
		if ( !is_null($start) and !is_null($extract) ) {
			$start = $_SESSION['database']->clearString($start);
			$extract = $_SESSION['database']->clearString($extract);
			$limit = "LIMIT $start, $extract";
		} else $limit = NULL;
		
		$sql = "SELECT
					t.id AS ticket_id,
					t.subject,
					UNIX_TIMESTAMP(t.open_date) AS open_date,
					t.status,
					UNIX_TIMESTAMP(t.last_msg_date) AS last_msg_date,
					h.base_name AS hosting_name
					FROM tickets AS t
					LEFT JOIN hostings AS h
					ON h.id = t.hosting_id
					WHERE t.status = 'replied'
					ORDER BY t.last_msg_date ASC $limit";
					
		$tickets_list = $_SESSION['database']->fetchObject($sql);
		// Check if tickets list is not empty
		if ( !isset($tickets_list[0]) ) return NULL;
		
		foreach ($tickets_list as $item) {
			$item->subject=stripslashes($item->subject);
		}
		return $tickets_list;
	}
	
	/**
	 * @brief Extract messages related to a given ticket
	 * @param ticket_id -> id of the ticket for witch we want to see the messages
	 * @param start -> First message to extract
	 * @param extract -> Number of messages to extract
	 * @return an array (NULL if ticket_id was an invalid number) with first element = ticket summary, and others = messages
	*/
	public function getTicketDetails($ticket_id, $start = NULL, $extract = NULL)
	{
		$ticket_id = $_SESSION['database']->clearString($ticket_id);
		
		if ( !is_null($start) and !is_null($extract) ) {
			$start = $_SESSION['database']->clearString($start);
			$extract = $_SESSION['database']->clearString($extract);
			$limit = "LIMIT $start, $extract";
		} else $limit = NULL;
		
		// Extract ticket's summary
		$req = "SELECT
					t.*,
					h.base_name AS hosting_name,
					u.username AS user_name
					FROM tickets AS t
					LEFT JOIN hostings AS h
					ON h.id = t.hosting_id
					LEFT JOIN users AS u
					ON u.id = t.user_id
					WHERE t.id = '$ticket_id'"; 
		$summary = $_SESSION['database']->fetchObject($req);
		// Check if ticket id was a valid number
		if ( !isset($summary[0]) ) return NULL;
		$summary[0]->subject = stripslashes($summary[0]->subject);
		$summary[0]->open_date = strtotime($summary[0]->open_date);
		// Extract messages
		$req = "SELECT
					m.id AS msg_id,
					UNIX_TIMESTAMP(m.posted) AS posted,
					m.is_reply,
					m.message
					FROM tickets_msg AS m
					WHERE m.ticket_id = '$ticket_id'
					ORDER BY m.posted DESC
					$limit";
		$messages = $_SESSION['database']->fetchObject($req);
		foreach ($messages as $item) {
			$item->message=stripslashes($item->message);
		}
		// if messages list is not empty, append it to results
		if ( !is_null($messages) )
			$results = array_merge((array)$summary, $messages);
		else
			$results = (array)$summary;

		return $results;
	} // End of getTicketDetails

	/**
	 * @brief Create a new ticket from a user request
	 * @param subject -> subject of the ticket
	 * @param message -> content of the ticket
	 * @param hosting_id -> id of the hosting entry to associate with this ticket (can be NULL)
	 * @return True if successfull, false otherwise
	*/
	public function userCreateTicket($subject, $message, $hosting_id=NULL)
	{
		$subject = $_SESSION['database']->clearString($subject);
		$message = $_SESSION['database']->clearString($message);
		$date_msg = time();
		$user_id=$_SESSION['user']->information_user->userid;
		$ticket_id = 0; // we actually don't know this value
		if ( is_null($hosting_id) ) {
			$hosting_entry='';
		} else {
			$hosting_id = $_SESSION['database']->clearString($hosting_id);
			$hosting_entry="hosting_id = '$hosting_id',";
		}
		
		// Addind message into database
		$sql1 = "INSERT INTO tickets_msg
				SET
					ticket_id  = '$ticket_id',
					posted = FROM_UNIXTIME($date_msg),
					is_reply = 'false',
					message = '$message'";
		$_SESSION['database']->execRequest($sql1);
		$msg_id = $_SESSION['database']->getInsertId();
		
		// Adding ticket infos in database
		$sql2 = "INSERT INTO tickets
				SET
					user_id = '$user_id',
					open_date = FROM_UNIXTIME($date_msg),
					first_msg_id = '$msg_id',
					last_msg_date = FROM_UNIXTIME($date_msg),
					last_msg_id = '$msg_id',
					status = 'asked',
					$hosting_entry
					subject = '$subject'";
		$_SESSION['database']->execRequest($sql2);
		$ticket_id = $_SESSION['database']->getInsertId();
		
		// Updating cache variable if needed
		if ( !is_null($this->user_tickets) ) {
			$this->user_tickets++;
		}
		
		// Updating ticket id for the message
		$sql3 = "UPDATE tickets_msg
				SET
					ticket_id = '$ticket_id'
				WHERE
					id = '$msg_id'";
		return $_SESSION['database']->execRequest($sql3);
	} // End of userCreateTicket
	
	/**
	 * @brief Check if a ticket delong to the current user
	 * @param ticket_id -> id of the ticket to check
	 * @return true if ticket if current user's one, false otherwise
	*/
	public function userCheckTicketId($ticket_id)
	{
		$user_id = $_SESSION['user']->information_user->userid;
		$ticket_id = $_SESSION['database']->clearString($ticket_id);
		
		$sql = "SELECT id FROM tickets
				WHERE id = '$ticket_id'
				AND user_id = '$user_id'";
		$result = $_SESSION['database']->fetchObject($sql);
		return ( isset($result[0]));
	} // End of userCheckTicketId
	
	/**
	 * @brief Add a response to a ticket (from the user)
	 * @param ticket_id -> id of the ticket to associate to the response
	 * @param message -> content of the response
	 * @return true if successfull, false otherwise
	*/
	public function  userAddResponse($ticket_id, $message)
	{
		if ( !$this->userCheckTicketId($ticket_id) ) return false;
		return $this->addResponse($ticket_id, $message, true);
	} // end of userAddResponse
	
	/**
	 * @brief Add a response to a ticket
	 * @param ticket_id -> id of the ticket to associate to the response
	 * @param message -> content of the response
	 * @param from_user -> true if the response comes from the user, false otherwise
	 * @return true if successfull, false otherwise
	*/
	public function addResponse($ticket_id, $message, $from_user)
	{
		$ticket_id = $_SESSION['database']->clearString($ticket_id);
		$message = $_SESSION['database']->clearString($message);
		$from_user = $_SESSION['database']->clearString($from_user);
		$is_reply=( $from_user==true ? 'false' : 'true' );
		$status = ( $is_reply=='true' ? 'replied' : 'asked' );
		$date_msg = time();
		
		$sql = "INSERT INTO tickets_msg SET
				ticket_id = '$ticket_id',
				posted = FROM_UNIXTIME($date_msg),
				is_reply = '$is_reply',
				message = '$message'";
		$_SESSION['database']->execRequest($sql);
		$msg_id = $_SESSION['database']->getInsertId();
		
		if ( !$msg_id) return false;
		$sql2 = "UPDATE tickets SET
					last_msg_date = FROM_UNIXTIME($date_msg),
					last_msg_id = '$msg_id',
					status = '$status'
				WHERE id='$ticket_id'";
		return $_SESSION['database']->execRequest($sql2);
	} // end of addResponse
	
	/**
	 * @brief Close a support ticket
	 * @param ticket_id -> id of the ticket to close
	 * @param fromUser -> true if called from a user's page, false otherwise
	 * @return true if successfull, false otherwise
	*/
	public function closeTicket($ticket_id, $from_user)
	{
		$ticket_id = $_SESSION['database']->clearString($ticket_id);
		$from_user = $_SESSION['database']->clearString($from_user);
		$status = ( $from_user==true ? 'closed_by_user' : 'closed_by_support' );
		$close_date = time();
		
		$sql = "UPDATE tickets SET
					status = '$status',
					closed_date = FROM_UNIXTIME($close_date)
				WHERE id='$ticket_id'";
		return $_SESSION['database']->execRequest($sql);
	} // end of closeTicket
	
	/**
	 * @brief Close a support ticket (from the user)
	 * @param ticket_id -> id of the ticket to close
	 * @return true if successfull, false otherwise
	*/
	public function  userCloseTicket($ticket_id)
	{
		if ( !$this->userCheckTicketId($ticket_id) ) return false;
		return $this->closeTicket($ticket_id, true);
	} // end of userCloseTicket
	
	/**
	 * @brief Get number of tickets for the current user
	 * @param None
	 * @return number of tickets for the user
	 *
	 * Get the total of support tickets for the current user.<br />
	 * This value is got the first time from the database (generating a SQL request) and is then stocked in a cache variable, so, other calls to this method won't generate another SQL request.
	*/
	public function userCountTickets() 
	{
		// Try to get the value from the cache
		if( !is_null($this->user_tickets) ) {
			return $this->user_tickets;
		}
		
		$user_id = $_SESSION['user']->information_user->userid;
		$req = "SELECT COUNT(id) AS total FROM tickets WHERE user_id='$user_id'";
		$result = $_SESSION['database']->fetchObject($req);
		$this->user_tickets = $result[0]->total;
		
		return $this->user_tickets;
	}
	
	/**
	 * @brief Get number of tickets pages for the current user, regarding the total count of tickets and the count of items to be shown per page
	 * @param None
	 * @return number of pages availables
	 *
	 * Calculate the total pages needed to show all the support tickets for the current user.
	*/
	public function userCountTotalPages() 
	{
		$items_count = $this->userCountTickets();
		$pages_count = intval($items_count / RECORD_BY_PAGE);
		if ( ($items_count % RECORD_BY_PAGE) != 0 ) {
			$pages_count++;
		}
		return $pages_count;
	}
	
	/**
	 * @brief Get the total of messages for a given ticket
	 * @param ticket_id Id of the ticket for witch we want to count the messages
	 * @return number of messages
	*/
	public function countTicketMessages( $ticket_id )
	{
		$ticket_id = $_SESSION['database']->clearString($ticket_id);
		if ( isset($this->ticket_messages[$ticket_id]) ) {
			return $this->ticket_messages[$ticket_id];
		}
		$req = "SELECT COUNT(id) AS total FROM tickets_msg WHERE ticket_id='$ticket_id'";
		$result = $_SESSION['database']->fetchObject($req);
		$this->ticket_messages[$ticket_id] = $result[0]->total;
		
		return $this->ticket_messages[$ticket_id];
	}
	
	/**
	 * @brief Get total of details pages for a given ticket, regarding the total count of messages and the count of items to be shown per page
	 * @param ticket_id Id of the ticket for witch we want the total of pages
	 * @return number of pages availables
	*/
	public function countTicketTotalPages( $ticket_id ) 
	{
		$items_count = $this->countTicketMessages( $ticket_id );
		$pages_count = intval($items_count / RECORD_BY_PAGE);
		if ( ($items_count % RECORD_BY_PAGE) != 0 ) {
			$pages_count++;
		}
		return $pages_count;
	}
	
	/**
	 * @brief Get total of tickets waiting for a support reply
	 * @param None
	 * @return number of tickets waiting for a support reply
	 *
	 * Get the total of support tickets waiting for a support reply.<br />
	 * This value is got the first time from the database (generating a SQL request) and is then stocked in a cache variable, so, other calls to this method won't generate another SQL request.
	*/
	public function countWaitingTickets() 
	{
		// Try to get the value from the cache
		if( !is_null($this->waiting_tickets) ) {
			return $this->waiting_tickets;
		}
		
		$req = "SELECT COUNT(id) AS total FROM tickets WHERE status = 'asked'";
		$result = $_SESSION['database']->fetchObject($req);
		$this->waiting_tickets = $result[0]->total;
		
		return $this->waiting_tickets;
	}
	
	/**
	 * @brief Get total of pages for tickets waiting for a supoprt reply, regarding the total count of messages and the count of items to be shown per page
	 * @param None
	 * @return number of pages availables
	*/
	public function countWaitingTicketsTotalPages() 
	{
		$items_count = $this->countWaitingTickets();
		$pages_count = intval($items_count / RECORD_BY_PAGE);
		if ( ($items_count % RECORD_BY_PAGE) != 0 ) {
			$pages_count++;
		}
		return $pages_count;
	}
	
	/**
	 * @brief Get total of tickets for witch the support made a reply
	 * @param None
	 * @return number of tickets for witch the support made a reply
	 *
	 * Get the total of support tickets for witch the support made a reply.<br />
	 * This value is got the first time from the database (generating a SQL request) and is then stocked in a cache variable, so, other calls to this method won't generate another SQL request.
	*/
	public function countRepliedTickets() 
	{
		// Try to get the value from the cache
		if( !is_null($this->replied_tickets) ) {
			return $this->replied_tickets;
		}
		
		$req = "SELECT COUNT(id) AS total FROM tickets WHERE status = 'replied'";
		$result = $_SESSION['database']->fetchObject($req);
		$this->replied_tickets = $result[0]->total;
		
		return $this->replied_tickets;
	}
	
	/**
	 * @brief Get total of pages for tickets for witch the support made a reply, regarding the total count of messages and the count of items to be shown per page
	 * @param None
	 * @return number of pages availables
	*/
	public function countRepliedTicketsTotalPages() 
	{
		$items_count = $this->countRepliedTickets();
		$pages_count = intval($items_count / RECORD_BY_PAGE);
		if ( ($items_count % RECORD_BY_PAGE) != 0 ) {
			$pages_count++;
		}
		return $pages_count;
	}

} // End of class
