<?php

/**
 * @class cron
 * @brief Manage, edit, add, delete, test Cronjobs
 * 
 * @author Benjamin Mercier
 * @data 12/08/2009
 * @version 0.1
*/
class cron 
{
	
	private $cron_records = null;
	
  /**
   * @brief List crons for the current hosting
   * @param hosting_id ID of the current hosting
   * @param start First record to extract (optional)
   * @param extract_number Number of record to extract (optional)
   * @return array or null if empty
  */
  public function userListCrons( $hosting_id, $start = null, $extract_number = null)
  {
    $hosting_id = $_SESSION['database']->clearString($hosting_id);
    
    if ( !is_null($start) and !is_null($extract_number)) {
      $start = $_SESSION['database']->clearString($start);
      $extract_number = $_SESSION['database']->clearString($extract_number);
      $limit = " LIMIT $start, $extract_number";
    } else $limit = null;
    
    $req = "SELECT id, address, UNIX_TIMESTAMP(created_at) AS created_at, execute_every, UNIX_TIMESTAMP(executed_at) AS executed_at, is_active 
            FROM service_cron WHERE hosting_id = '$hosting_id' ORDER BY created_at DESC$limit";
    $query = $_SESSION['database']->fetchObject($req);
    return $query;    
  }
	
	/**
	 * @brief add a Cronjob for current user
	 * @param address Url of the script to call
	 * @param frequency  Frequency of the task execution
	 * @param first_start Date/Time for the first execution
	 * @return 0 : Address is not openable
	 * @return 1 : Cronjob added
	 * @return 2 : Limit of cronjob for the current offer is reached
	 *
	 * @todo Manage the 'first_start' parameter
	*/
	public function userAddCron( $address, $frequency, $first_start, $active=true )
	{	
		// Check Time for executing
		$frequency = intval($frequency);
		if ( $frequency == CRON_NO_SPECIFIED_TIME ) {
			$active=false;
		} elseif ( $frequency < CRON_MIN_TIME ) {
			$frequency = CRON_MIN_TIME;
		}
		// Check if address is openable
		$address_test = $this->checkAddress($address);
		if ( !$address_test ) return 0;
		// Check quota
		if ( $_SESSION['hosting']->information_hosting->offer_crons_number >= 0 ) {
			$current_number_crons = $this->countCronjobs( $_SESSION['hosting']->information_hosting->id );
			if ( $current_number_crons >= $_SESSION['hosting']->information_hosting->offer_crons_number ) return 2;
		}
		// Get the ID of the current hosting
		$hosting_id = $_SESSION['hosting']->information_hosting->id;
		$this->addCron( $hosting_id, $address, $frequency, true);
		return true;
	} // End of userAddCron
	
	
	/**
	 * @brief Active an deactivated cron
	 * @param cron_id ID of the cron
	 * @return : 0 Cron is not found
	 * @return : 1 Cron activated
	 * @return : 2 Cron is already activated
	*/
	public function userActiveCron( $cron_id )
	{
	    $cron = $_SESSION['database']->clearString($cron_id);
	    $req = "SELECT hosting_id, is_active FROM service_cron WHERE id = '$cron'";
	    $query = $_SESSION['database']->fetchObject($req);
	    if ( count($query) == 0 ) return 0;
	    if( $query[0]->hosting_id != $_SESSION['hosting']->information_hosting->id )
	      throw new myException('Hosting_id is not attribued for this cron');
	    if ( $query[0]->is_active == 'true' ) return 2;
	    $req = "UPDATE service_cron SET is_active = 'true' WHERE id = '$cron'";
	    $_SESSION['database']->execRequest($req);
	    return 1;
	}
	
	/**
	 * @brief Deactivate a cron
	 * @param cron_id : ID of the cron
	 * @return : 0 Cron is not found
	 * @return : 1 Cron deactivated
	 * @return : 2 Cron is already deactivated
	*/
	public function userDeactiveCron( $cron_id )
	{
	    $cron = $_SESSION['database']->clearString($cron_id);
	    $req = "SELECT hosting_id, is_active FROM service_cron WHERE id = '$cron'";
	    $query = $_SESSION['database']->fetchObject($req);
	    if ( count($query) == 0 ) return 0;
	    if( $query[0]->hosting_id != $_SESSION['hosting']->information_hosting->id )
	      throw new myException('Hosting_id is not attribued for this cron');
	    if ( $query[0]->is_active == 'false' ) return 2;
	    $req = "UPDATE service_cron SET is_active = 'false' WHERE id = '$cron'";
	    $_SESSION['database']->execRequest($req);
	    return 1;
	}
	
	/**
	 * @brief Delete a cron for the current hosting
	 * @param cron_id Id of the cron to delete
	 * @return True or false if not found
	*/
	public function userDeleteCron( $cron_id )
	{
	  $cron_id_s = $_SESSION['database']->clearString($cron_id);
	  $req = "SELECT hosting_id FROM service_cron WHERE id ='$cron_id_s'";
	  $query = $_SESSION['database']->fetchObject($req);
	  if ( count($query) == 0 ) return false;
	  if ( $query[0]->hosting_id != $_SESSION['hosting']->information_hosting->id ) 
	    throw new myException('Hosting_id is not attribued for this cron');
    $this->deleteCron( $cron_id );
	  return true;
	} // End of userDeleteCron
	
	/**
	 * @brief try to open an url by fsockopen.
	 * @param address web Address
	 * @return true Web respond
	 * @return false Web did not respond or not ready
	*/
	public function checkAddress( $address )
	{
		if ( !textVerification::verifUrl($address) ) return false;
		
		$url_info = parse_url($address);
		if ( $url_info['scheme'] == 'http' ) $port = 80;
		elseif ( $url_info['scheme'] == 'https' ) $port = 443;
		else $port = 80;
		
		$handle = fsockopen( $url_info['host'], $port, $errno, $errstr, CRON_TIMEOUT);
		if ($handle !== false) {
			fclose($handle);
			return true;
		} else {
			return false;
		}	
	} // End of checkAddress
  
  /**
   * @brief Select all cronjob to execute. For server.
   * @todo make this function when the daemons are dev.
  */
	public function serverListToTestCrons()
	{
	}
	
	/**
	 * @brief Count total cronjobs for a user
	 * @param hosting_id : ID of the hosting to count
	 * @param (optionnal) active_cron : True of False, count only active jobs, or count total jobs
	 * @return Total of cronjobs 
	*/
	private function countCronJobs( $hosting_id, $only_active = false )
	{
		$hosting_id = $_SESSION['database']->clearString($hosting_id);
		if ( $only_active ) $clause = " AND is_active = 'true'";
		else $clause = null;
		$req = "SELECT COUNT(id) AS total FROM service_cron WHERE hosting_id = '$hosting_id'$clause";
		$query = $_SESSION['database']->fetchObject($req);
		return $query[0]->total;		
	}
	
	/**
	 * @brief adding Cron
	 * @param hosting_id Id of the hosting
	 * @param address  Address to cron
	 * @param time Time in seconds to re-execute
	 * @param is_active Activation of the cron (true/false)
	*/
	private function addCron( $hosting_id, $address, $time, $is_active)
	{
	  $hosting_id = $_SESSION['database']->clearString($hosting_id);
	  $address = $_SESSION['database']->clearString($address);
	  $time = $_SESSION['database']->clearString($time);
	  
	  if ( $is_active ) $is_active = 'true';
	  else $is_active = 'false';
	  
	  $req = "INSERT INTO service_cron
	          SET 
	            hosting_id = '$hosting_id',
	            address = '$address',
	            created_at = NOW(),
	            execute_every = '$time',
	            is_active = '$is_active'";
    $query = $_SESSION['database']->execRequest($req);
    return true;	  
	}
	
	/**
	 * @brief delete cron identified by id
	 * @param cron_id  Id of the cron
	 * @return true
	*/
	private function deleteCron( $cron_id )
	{
	  $cron_id = $_SESSION['database']->clearString($cron_id);
	  $req = "DELETE FROM service_cron WHERE id = '$cron_id'";
	  $_SESSION['database']->execRequest($req);
	  return true;
	}
	
	/**
	 * @brief Get number of all crontab records for the current hosting
	 * @return number of history records registered for the user
	*/
	public function userCountCronRecords() 
	{
		if( !is_null($this->cron_records) ) {
			return $this->cron_records;
		}
		$hosting_id = $_SESSION['hosting']->information_hosting->id;
		$req = "SELECT COUNT(id) AS total FROM service_cron WHERE hosting_id = '$hosting_id'";
		$result = $_SESSION['database']->fetchObject($req);
		$this->cron_records = $result[0]->total;
		return $this->cron_records;
	}
	
	/**
	 * @brief Get number of crons records pages, regarding the total count of records and the count of items to be shown per page
	 * @return number of pages availables
	*/
	public function userCountTotalPages() 
	{
		$items_count = $this->userCountCronRecords();
		$pages_count = intval($items_count / RECORD_BY_PAGE);
		if ( ($items_count % RECORD_BY_PAGE) != 0 ) {
			$pages_count++;
		}
		return $pages_count;
	}

}
?>