<?php
/**
 * Todo class
 * 
 * Provides methods related to project task module
 * 
 * @package linea21\modules\project
 * @author $Author$ - Simon Georget <simon@linea21.com>
 * @version $Id$ 
 * @access public
 * @license http://opensource.org/licenses/gpl-3.0.html
 * Content Management
 */

class projectTask {
    
    
	public $available_status = array('todo', 'wip', 'done');
	public $available_frequencies = array('noreminder' => 'NO REMINDER', '8days' => 'INTERVAL 8 DAY', '15days' => 'INTERVAL 15 DAY', '1month' => 'INTERVAL 1 MONTH', '3months' => 'INTERVAL 3 MONTH', '6months' => 'INTERVAL 6 MONTH', '1year' => 'INTERVAL 1 YEAR');
	
	protected $dispatcher = null;


	public function __construct()
	{
		$this->dispatcher = $GLOBALS['dispatcher'];
	}

	public function __call($method, $arguments)
	{
		$event = $this->dispatcher->notifyUntil(new sfEvent($this, 'task.extensible_function', array(
				'method'    => $method,
				'arguments' => $arguments
		)));
		if (!$event->isProcessed())
		{
			throw new Exception(sprintf('Call to undefined method %s::%s.', get_class($this), $method));
		}

		return $event->getReturnValue();
	}


	/**
	 * checkDataIntegrity()
	 * Vérification intégrité des données
	 *
	 * @access public
	 * @param array $a
	 * @return boolean true
	 * si verifié, sinon string 'message d'erreur'
	 */

	public function checkDataIntegrity($a)
	{
		// Filter data event + return value
		$r = $this->dispatcher->filter(new sfEvent($this, 'task.before_datacheck', array('data' => $a)), $a);
		$a = $r->getReturnValue();

		if (strlen($a['label']) < 3) return _t('task','no_label');

        if(isset($a['task_date_crea'])) {
            $r = checkdate_validity($a['task_date_crea'], _t('validation','invalid_publication_date'));
            if(is_string($r)) return $r;
        }
        if(isset($a['task_date_done'])) {
            $r = checkdate_validity($a['task_date_done'], _t('validation','invalid_publication_date'));
            if(is_string($r)) return $r;
        }

		// Notify the beginning of the current method
		$this->dispatcher->notify(new sfEvent($this, 'task.after_datacheck', array('data' => $a)));

		return true;
	}

    /**
     * getTmpID()
     * creat a negative ID as temporary ID for Project
     * @return integer
     */
	public function getTmpID() {
	    
	    // for the use of project tasks
	    // we create tmp actionID stored in session fore db recording and we will update it later
	    if(!isset($_SESSION['tmpActionID'])) {
	        // only available from PHP 7+
			if(function_exists('random_int')) {
				$id = random_int(-99999, -1);
			} else {
				$id = rand(-99999, -1);
			}
	        $_SESSION['tmpActionID'] = $id;
	    } else {
	        $id = $_SESSION['tmpActionID'];
	    }
	    return $id;
	}
	
	/**
	 * updateTmpID()
	 * update temporary Project ID after inserting Project in DB
	 * @param integer $id
	 * @param object $sql_object
	 * @return boolean
	 */
	public function updateTmpID($id, $sql_object) {
	    
	    // finally we change temporary actionID in task records if needed
	    if(isset($_SESSION['tmpActionID'])) {
	        $q = "UPDATE " . T_PROJECT_TASK . " SET task_project_id = " . $id. " WHERE task_project_id = ".$_SESSION['tmpActionID'].";";
	        $res = $sql_object->DBQuery($q);
	        unset($_SESSION['tmpActionID']); // we remove session variable
	    }
	    
	    return true;
	    
	}

	/**
	 * add()
	 * Add task entry with given values ($a)
	 *
	 * @access public
	 * @param array $a
	 * @param object $sql_object
	 * @return integer $last_id
	 */
	public function add($a, $sql_object) {

		global $l21auth;
		
		// Filter data event + return value
		$r = $this->dispatcher->filter(new sfEvent($this, 'task.before_add', array('data' => $a)), $a);
		$a = $r->getReturnValue();
		
		$a = array_map('sanitize_string', $a);

		$a = $sql_object->DBescape($a);

		$a['label'] = strip_input(trim($a['label']), false);
	    $a['status'] = strip_input(trim($a['status']), false);
		$a['user_id'] = strip_input(trim($a['user_id']), false);
		$a['project_id'] = strip_input(trim($a['pid']), false);
		$a['range'] = 0;
		
		if($a['status'] == 'done') $task_date_done = 'NOW()'; else $task_date_done = "'0001-01-01 00:00:00'";
		

		$q = "INSERT INTO " . T_PROJECT_TASK . " (task_label, task_status, task_user_id, task_date_done, task_project_id, task_range, task_reminder_freq, task_date_crea) VALUES('" . $a['label'] . "', '" . $a['status'] . "', '" . $a['user_id'] . "', " . $task_date_done . ", '" . $a['project_id'] . "', '" . $a['range'] . "', '" . $a['reminder_freq'] . "', now());";

		$last_id = $sql_object->DBInsert ($q, 1);
		
		// we log add task
		if(is_numeric($last_id))	logfile(LOG_MAINFILE, array('[action] add project task', 'ID='.$last_id, 'project_ID='.$a['project_id'], 'by_id='.$a['user_id'], 'by_login='.$l21auth->GetSessionElement('login')));

		// Notify the end of the current method
		$this->dispatcher->notify(new sfEvent($this, 'task.after_add', array('data' => $a, 'id' => $last_id)));

		return $last_id;
	}

	/**
	 * get_project_tasks()
	 * Get all tasks associated to a gven project ($project_id)
	 *
	 * @access public
	 * @param integer $project_id
	 * @param object $sql_object
	 * @return array $data
	 */
	public function get_project_tasks($project_id, $sql_object) {
	    
		// Notify the end of the current method
	    $this->dispatcher->notify(new sfEvent($this, 'task.get_project_tasks', array('id' => $project_id)));

		$data = $sql_object->DBSelect(SQL_get_project_tasks($project_id));

		return $data;
	}

	/**
	 * get_task()
	 * Get one task by ID
	 *
	 * @access public
	 * @param integer $id
	 * @param object $sql_object
	 * @return array $data
	 */
	public function get_task($id, $sql_object) {
	    
	    // Notify the end of the current method
	    $this->dispatcher->notify(new sfEvent($this, 'task.get_task', array('id' => $id)));
	    
	    $data = $sql_object->DBSelect(SQL_get_task($id));
	    
	    return $data;
	}

	/**
	 * modify()
	 * Edit task entry with new values ($a)
	 *
	 * @access public
	 * @param integer $id
	 * @param array $a
	 * @param object $sql_object
	 * @return bool $r
	 */
	public function modify($id, $a, $sql_object) {
		
		// Notify the end of the current method
		$this->dispatcher->notify(new sfEvent($this, 'task.modify', array('id' => $id, 'data' => $a)));
		
		$a = array_map('sanitize_string', $a);
		
		$a = $sql_object->DBescape($a);
		
		$a['label'] = strip_input(trim($a['label']), false);
		$a['status'] = strip_input(trim($a['status']), false);
		$a['user_id'] = strip_input(trim($a['user_id']), false);
		$a['project_id'] = strip_input(trim($a['pid']), false);
		
		// we get old status value to see if any need to update 'task_date_done' field
		$r = $this->get_task($id, $sql_object);

        $task_date_done = isset($a['task_date_done']) ?  "'".formatDate($a['task_date_done'], true) ." 00:00:00'" : "'".$r[0]['task_date_done']."'";
        $task_date_crea = isset($a['task_date_crea']) ?  "'".formatDate($a['task_date_crea'], true) ." 00:00:00'" : "'".$r[0]['task_date_crea']."'";
		
		if($a['status'] == 'done' && $r[0]['task_status'] != 'done') $task_date_done = 'NOW()'; else $task_date_done = $task_date_done; // previous value 'task_date_done';
		if($a['status'] != 'done' && $r[0]['task_status'] == 'done') $task_date_done = "'0001-01-01 00:00:00'";

		
		$q = "UPDATE " . T_PROJECT_TASK . " SET task_label = '" . $a['label']. "', task_status = '" . $a['status']. "', task_user_id = '" . $a['user_id']. "', task_date_crea = " . $task_date_crea. ", task_date_done = " . $task_date_done. ", task_reminder_freq = '".$a['reminder_freq']."' WHERE task_id = ".$id.";";

		$r = $sql_object->DBQuery($q);
		
		return $r;
	}



	/**
	 * delete()
	 * Delete task entry by changing field value
	 *
	 * @access public
	 * @param integer $id
	 * @param object $sql_object
	 * @return bool $r
	 */
	public function delete($id, $sql_object) {

		global $l21auth;
		
		// Notify the end of the current method
		$this->dispatcher->notify(new sfEvent($this, 'task.delete', array('id' => $id)));

		$id = $sql_object->DBEscape($id);
		$q = "UPDATE ". T_PROJECT_TASK . " SET task_deleted='Y' WHERE task_id='".$id."'";
		$r = $sql_object->DBQuery($q);
		
		// we log delete action
		if($r)	logfile(LOG_MAINFILE, array('[action] delete todo task', 'ID='.$id, 'by_id='.$l21auth->GetSessionElement('id'), 'by_login='.$l21auth->GetSessionElement('login')));

		return $r;
	}
	
	/**
	 * update_lastsend()
	 * Update the latest date value field (task_reminder_lastdate) in database
	 *
	 * @access public
	 * @param integer $id
	 * @param object $sql_object
	 * @return bool $r
	 */
	public function update_lastsend($id, $sql_object) {
	    
	    // Notify the beginning of the current method
	    $this->dispatcher->notify(new sfEvent($this, 'task.update_lastsend', array('id' => $id)));
	    
	    $id = $sql_object->DBEscape($id);
	    $q = "UPDATE ". T_PROJECT_TASK . " SET task_reminder_lastdate = NOW() WHERE task_id='".$id."'";
	    $r = $sql_object->DBQuery($q);
	    
	    // we log delete action
	    if($r)	logfile(LOG_MAINFILE, array('[action] change task reminder_lastdate field value', 'ID='.$id));
	    
	    return $r;
	}



	/**
	 * resources::changeRanges()
	 * changes task range
	 *
	 * @access public
	 * @param array : format Array ( [0] => Array ( [id] => 8 ) [1] => Array ( [id] => 59 ) [2] => Array ( [id] => 9 ) [3] => Array ( [id] => 5 ) ) 
	 * @param object $sql_object
	 * @return bool $result
	 */
	
	function changeRanges($array, $sql_object)
	{

	    foreach ($array as $key => $value) {
	        // print_r( $value);
	        $query = "UPDATE " . T_PROJECT_TASK . " SET task_range ='".($key+1)."', task_last_modify = task_last_modify WHERE task_id ='" . $value['id'] . "';";
	        $result = $sql_object->DBQuery($query);
	    }
	    
	    // Notify the beginning of the current method
	    $this->dispatcher->notify(new sfEvent($this, 'task.change_ranges', array('data' => $array)));
	    
	    return $result;
	}

}
?>