<?
/**
 * VoiceOne Webservices Interface
 *
 * @package voiceone_webservices
 * @subpackage  queues
 */ 

//******************************************************************************
//******************               QUEUE                   *********************
//******************************************************************************
// ---- getQueue(id:int):Queue[] -----------------------------------------------
/**
 * Get Queue by id or get all Queues if id is not defined.
 * 
 * @param integer queueID. If none specified, then all queues are returned
 * @return array queue[] using the database record structure including a list of all members for each queue as array in field "member"
 * @see putQueue
 * @see delQueue
 * @see getQueueByName
 * @todo fix group export to be xml compliant (do not use numeric tags)
 */
function getQueue($id) {
  global $db;
  if ($id!="") $condition="WHERE id=$id ";
  $qry="SELECT * FROM cw_queue $condition ORDER BY name";
  $res=$db->Execute($qry);
  while ($arr=$res->FetchRow()) { 
    //extract the attributes from the cw_option_entity
    $arr["options"]=array();
    $qry="SELECT * FROM cw_option_entity WHERE entity_id = ".$arr["id"];
    $res2=$db->Execute($qry);
    while($arr2=$res2->FetchRow()){
      $arr["options"][]=array(
          "key" => $arr2["option_id"],
          "value" => $arr2["value"]
        );
    }
    //extract the member from the queue_member table
    $arr["member"]=array();
    $qry="SELECT `member_id`,`penalty` FROM `cw_queue_member` WHERE `queue_id`=".$arr["id"]." ORDER BY `penalty` ";
    $res2=$db->Execute($qry);
    while($arr2=$res2->FetchRow()){
      $arr["member"][]=array(
      		"id" => $arr2["member_id"],
          "penalty" => $arr2["penalty"]
      	);
    }
    //return array
    $ret[]=$arr;
  }
  return $ret;
}
// ---- getQueuebyName($name:string):Queue[] -----------------------------------
/**
 * Get Queue by name
 * 
 * @param string $name.
 * @return array queue[] using the database record structure including a list of all members for each queue as array in field "member"
 * @see putQueue
 * @see delQueue
 * @see getQueue
 * @todo fix group export to be xml compliant (do not use numeric tags)
 */
function getQueueByName($name) {
  global $db; 
  $qry="SELECT * FROM cw_queue WHERE name='".string2sql($name)."' ORDER BY name";
  $res=$db->Execute($qry);
  while ($arr=$res->FetchRow()) { 
    //extract the attributes from the cw_option_entity
    $arr["options"]=array();
    $qry="SELECT * FROM cw_option_entity WHERE entity_id = ".$arr["id"];
    $res2=$db->Execute($qry);
    while($arr2=$res2->FetchRow()){
      $arr["options"][]=array(
          "key" => $arr2["option_id"],
          "value" => $arr2["value"]
        );
    }
    //extract the member from the queue_member table
    $arr["member"]=array();
    $qry="SELECT `member_id`,`penalty` FROM `cw_queue_member` WHERE `queue_id`=".$arr["id"]." ORDER BY `penalty` ";
    $res2=$db->Execute($qry);
    while($arr2=$res2->FetchRow()){
      $arr["member"][]=array(
      		"id" => $arr2["member_id"],
          "penalty" => $arr2["penalty"]
      	);
    }
    //return array
    $ret[]=$arr;
  }
  return $ret;
}
// ---- putQueue(queue:Queue):int ----------------------------------------------
/**
 * Create a new Queue or recreate the queue it it exists. Update Asterisk afterwards.
 * 
 * @param array $queue  (queue:Queue)
 * @param boolean $keepId default: true=keep Id regardless of the name; false=keep Id only if name matches
 * @return integer queueID 
 * @see putQueue
 * @see delQueue
 */
function putQueue($queue, $keepId=true) {
  global $db;
  /***********************************/
  // Request for Update? 
  // By name or by id?  
  // Update via edit would be by id
  // Update via plugin would be by name
  // Otherwise we would risk to override a complete different entity via a plugin
  // So $keepId should be false if called via putPlugin.
  /***********************************/
  //go to the alterQueue function
  if ((isset($queue["id"])) and ($queue["id"] != "") and ($keepId == true)) {
    // id is set for new queue and must be used       
      $entity["id"] = $queue["id"];
      delQueue($entity["id"]);      
  } elseif ((isset($queue["name"])) and ($queue["name"] != "") and ($keepId == false)) {
    // name is set for new queue and must be used
    $curQueue = getQueueByName($queue["name"]);
    if ($curQueue[0]['name'] == $queue['name']) {
      // name matches, so get the id of the existing queue
      $entity["id"] = $curQueue[0]['id'];
      delQueue($entity["id"]);      
    }
  }
  //create a new entity. use the existing id if this is an update
  $entity["type"]=QUEUE;
  $entity_id=putEntity($entity);
  if (is_object($entity_id) or $entity_id==0) return 0;
  //insert in cw_queue
  $qry = "INSERT INTO cw_queue (`id`,`name`) VALUES ($entity_id,'".string2sql($queue["name"])."')";
  $res=$db->Execute($qry);
  if ($res===false) return new soap_fault('Server','','Queue creation error, mysql INSERT command failed'); 
  //insert the queue property in the ast_config table
  putAstConfig("queues.conf", "queue_$entity_id", "", "", "Queue ".$queue["name"], 1);  
  if(is_array($queue["options"])){
    foreach ($queue["options"] as $i=>$o) {
      $option_id=$o["key"];
      $value=$o["value"];   
      //retrieve the option name
      $qry="SELECT name,type FROM cw_option WHERE id=$option_id";
      $res=$db->Execute($qry);
      $arr=$res->FetchRow();
      $option_name=$arr["name"];
      //insert/update the option value in the cw_option_entity table
      $qry="SELECT * FROM cw_option_entity WHERE option_id=$option_id AND entity_id=$entity_id";
      $res=$db->Execute($qry);
      if ($res->RecordCount()==0) $qry="INSERT INTO cw_option_entity (option_id,entity_id,value) VALUES ($option_id,$entity_id,'".string2sql($value)."')";
      else $qry="UPDATE cw_option_entity  set value='".string2sql($value)."' WHERE option_id=$option_id AND entity_id=$entity_id";
      $db->Execute($qry);
      //insert in ast_config
      putAstConfig("queues.conf", "queue_$entity_id", $option_name, $value);
    }
  }
  //insert the members into the queue in the ast_config
  $res=memberToQueue($entity_id,$queue["member"]);
  if ($res===false) return 0;
  //if asterisk is ON, reload extensions
  $status=pbxSwitch("status");
  if($status=="ON") sendCommand("reload");
  //return value
  return $entity_id;
}
// ---- delQueue(id:int):int ---------------------------------------------------
/**
 * Delete a queue by ID
 * 
 * @param integer $queueID
 * @return integer 1 
 * @see getQueue
 * @see putQueue
 */
function delQueue($id) {
  global $db;
  //remove the entity from the asterisk tables
  $ret=delEntity($id); 
  //delete entry from cw_queue 
  $qry="DELETE FROM cw_queue WHERE id=$id";
  $res=$db->Execute($qry);
  if ($res===false) return new soap_fault('Server','','Queue remove error, mysql DELETE command failed');
  //delete entry from cw_queue_member
  $qry="DELETE FROM cw_queue_member WHERE queue_id=$id";
  $res=$db->Execute($qry);
  if ($res===false) return new soap_fault('Server','','Queue-member remove error, mysql DELETE command failed');
  //delete entry from cw_option_entity
  $qry="DELETE FROM cw_option_entity WHERE entity_id=$id";
  $res=$db->Execute($qry);
  if ($res===false) return new soap_fault('Server','','Queue-member remove error, mysql DELETE command failed');
  //remove the queue related entry in the ast_config table
  $res=delAstConfig("queues.conf","queue_$id");
  //return value
  return 1;
}
// ---- putQueueGeneralOtpion(tag: string, optionsArr: AssociativeArray):int ---
function putQueueGeneralOption($tag, $optionsArr){
  global $db;
  //retrieve filename and section name
  $qry="SELECT * FROM cw_config_file WHERE tag='".$tag."'";
  $res=$db->Execute($qry);
  if($res!==false){
    $arr=$res->FetchRow();
    $filename=$arr["file"];
    $category=$arr["category"];
    //get all tag option
    $allOptionsArr=getConfOption('',$tag,SECTION_GENERAL);
    //insert the queue property in the ast_config table  
    if((is_array($optionsArr))&&(is_array($allOptionsArr))){
      foreach($optionsArr as $opt) $optionsAssArr[$opt["key"]]=$opt["value"];
      foreach ($allOptionsArr as $i=>$o) {
        $option_id=$o["id"];
        $value=$o["value"]; 
        //retrieve the option name
        $qry="SELECT name FROM cw_option WHERE id=".$option_id."";
        $res=$db->Execute($qry);
        $arr=$res->FetchRow();
        $option_name=$arr["name"];
        //delete the queue property in the ast_config table
        delAstConfig($filename,$category, $option_name);
        if(@array_key_exists($option_id,$optionsAssArr)){
          $commented="0";
          $value=$optionsAssArr[$option_id];
          //insert in ast_config
          putAstConfig($filename, $category, $option_name, $value);
        }else $commented="1";
        $qry="UPDATE cw_option set value='".string2sql($value)."', commented=".$commented." WHERE id=".$option_id."";
        $db->Execute($qry);  
  		}
		}else if(is_array($allOptionsArr)){ //passed an empty options array
  	  foreach ($allOptionsArr as $i=>$o) {
        $option_id=$o["id"];
        $value=$o["value"];      
        //retrieve the option name
        $qry="SELECT name FROM cw_option WHERE id=".$option_id."";
        $res=$db->Execute($qry);
        $arr=$res->FetchRow();
        $option_name=$arr["name"];
        //delete the queue property in the ast_config table
        delAstConfig($filename,$category, $option_name);
        $commented="1";
  			$qry="UPDATE cw_option set value='".string2sql($value)."', commented=$commented WHERE id=$option_id";
        $db->Execute($qry);
      }
    } 
  }else return 0;
  //if asterisk is ON, reload asterisk
  $status=pbxSwitch("status");
  if($status=="ON") sendCommand("reload");
  return 1;
}
// ---- getQueueFromMember(member:int, penalty:int):QueueArray -----------------
//      this function is private
function getQueueFromMember($member){
  global $db;
  $ret=array();
  //retrieve queues joined by the member
  $qry="SELECT `queue_id`,`penalty` FROM `cw_queue_member` WHERE `member_id`=$member ";
  $res=$db->Execute($qry);
  while($arr=$res->FetchRow()){
    $ret[]=array(
    		"id" => $arr["queue_id"],
        "penalty" => $arr["penalty"]
    	);
  } 
  return $ret;
}
// ---- putQueueMember(queue:int, member:int, penalty:int):int -----------------
//      this function is private
function putQueueMember($queue,$member,$penalty=0){
  global $db;
  //insert member
  if($member!=""){
    $qry="INSERT INTO cw_queue_member (`queue_id`,`member_id`,`penalty`) VALUES ($queue,$member,$penalty)";
    $res=$db->Execute($qry);
    if ($res===false) return false;
    $agentArr=getAgent($member);
    $value="Agent/".$agentArr[0]["extension"].",".$penalty;
    $res=putAstConfig("queues.conf","queue_$queue","member",$value);    
    if ($res===false) $ret=$ret and 0; else $ret=$ret and 1;    
  }
  return $ret;
}
// ---- delQueueMember(member:int):int -----------------------------------------
//      this function is private
function delQueueMember($member){
  global $db;
  //retrieve queues joined by the member
  $joinedQueueArr=getQueueFromMember($member);
  //delete member from ast_config
  $ret=getAgent($member);
  if((is_array($ret))&&(is_array($joinedQueueArr))){
    $agent=$ret[0];
    foreach($joinedQueueArr as $joinedQueue){
    	$value="Agent/".$agent["extension"].",".$joinedQueue["penalty"];
      delAstConfig("queues.conf","queue_".$joinedQueue["id"],"member",$value);
    }
  }
  //delete member from cw_queue_member
  $qry="DELETE FROM cw_queue_member WHERE `member_id`=$member";
  $res=$db->Execute($qry);
  //return
  if($res!==false) return 1; 
  return 0;
}
// ---- memberToQueue(queue:int, member:queueMember[]):int ---------------------
//      this function is private
function memberToQueue($queue_id,$member) {
  global $db;
  $ret=1;
  //delete old members from cw_queue_member
  $qry="DELETE FROM cw_queue_member WHERE `queue_id`=$queue_id";
  $res=$db->Execute($qry);
  //delete old members from ast_config
  $res=delAstConfig("queues.conf","queue_$queue_id","member");
  //insert members
  if(is_array($member)){
  	ksort($member);
    foreach($member as $m){
      $qry="INSERT INTO cw_queue_member (`queue_id`,`member_id`,`penalty`) ";
      $qry.="VALUES (".$queue_id.",".$m["id"].",".$m["penalty"].")";
      $res=$db->Execute($qry);
      if ($res===false) return false;
      $agentArr=getAgent($m["id"]);
      $value="Agent/".$agentArr[0]["extension"].",".$m["penalty"];
      $res=putAstConfig("queues.conf","queue_$queue_id","member",$value);    
      if ($res===false) $ret=$ret and 0; else $ret=$ret and 1;
    }    
  }
  return $ret;
}
//******************************************************************************
//******************               AGENT                   *********************
//******************************************************************************
// ---- getAgent(id:int):AgentArray --------------------------------------------
function getAgent($id){
  global $db;
  if((trim($id)!="")&&($id!=0)) $condition="WHERE id=$id ";
  $qry="SELECT * FROM cw_agent $condition ORDER BY `extension`";
  $res=$db->Execute($qry);
  while($arr=$res->FetchRow()) {
    $arr["joined_queues"]=getQueueFromMember($arr["id"]);
    $ret[]=$arr;
  }
  return $ret;
}
// ---- putAgent(agent:Agent):int ---------------------------------------------
function putAgent($agent){
  global $db;
  //If exist, delete old agent
  if((isset($agent["id"]))and($agent["id"]!="")){
    $entity["id"]=$agent["id"];
    delAgent($agent["id"]);     
  }          
  //create a new entity. use the existing id if this is an update
  $entity["type"]=AGENT;
  $entity_id=putEntity($entity);
  if(is_object($entity_id) or $entity_id==0) return 0;
  //insert in cw_agent
  $qry="INSERT INTO cw_agent (`id`,`client`,`extension`,`username`,`password`) ";
  $qry.="VALUES ($entity_id,'".string2sql($agent["client"])."','".string2sql($agent["extension"])."','".string2sql($agent["username"])."','".string2sql($agent["password"])."')";
  $res=$db->Execute($qry);
  if($res===false) return new soap_fault('Server','','Agent creation error, mysql INSERT command failed'); 
  //insert the agent property in the ast_config table    
  $value=$agent["extension"].",,";
  putAstConfig("agents.conf", "agents", "agent", $value);  
  //if agent joined some queue, put it in
  if(is_array($agent["joined_queues"])){
    foreach($agent["joined_queues"] as $q){
      putQueueMember($q["id"],$entity_id,$q["penalty"]);
    }
  }
  //if asterisk is ON, reload asterisk
  $status=pbxSwitch("status");
  if($status=="ON") sendCommand("reload");
  //return value
  return $entity_id;
}
// ---- delAgent(id:int):int ---------------------------------------------------
function delAgent($id){ 
  global $db;
  //retrieve client informations
  if((trim($id)=="")||($id==0)) return 0;
  $agent=getAgent($id);
  $agent=$agent[0];
  //delete agent from queue members
  $ret=delQueueMember($id);
  //remove the entity from the asterisk tables
  $ret=delEntity($id); 
  //delete entry from cw_agent 
  $qry="DELETE FROM cw_agent WHERE id=$id";
  $res=$db->Execute($qry);
  if ($res===false) return new soap_fault('Server','','Agent remove error, mysql DELETE command failed');
  //remove the queue related entry in the ast_config table
  $value=$agent["extension"].",,";
  $res=delAstConfig("agents.conf", "agents", "agent", $value);
  //return value
  return 1;
}
// ---- getAgentFromEntity(client:int):Agent -----------------------------------
function getAgentFromEntity($client){
  global $db;
  if((trim($client)=="")||($client==0)) return 0;
  $qry="SELECT * FROM cw_agent WHERE client='".$client."' ORDER BY `extension`";
  $res=$db->Execute($qry);
  if($res!==false){
    $arr=$res->FetchRow(); 
    return $arr["id"];
  }
  return 0;
}
// ---- getRegisteredAgent():StringArray ---------------------------------------
function getRegisteredAgent() {
  global $db;
  $ret=array();
  $res=sendCommand("show agents");
  if($res!=""){
    $lines=explode("\n",$res);
    foreach ($lines as $l){
      if(strpos($l,"not logged in")===false){
        $exten=substr($l,0,strpos($l,"  "));
        if(is_numeric(trim($exten))) $ret[]=trim($exten);
      }
    }
  }
  return $ret;
}
// ---- logoffAgent(id:int):int ------------------------------------------------
function logoffAgent($id){ 
  global $db;
  //get agent
  $agent=getAgent($id);
  $agent=$agent[0];
  //logoff agent
  $extension=$agent["extension"];
  if($extension=="") return 0; 
  $res=sendCommand("agent logoff  Agent/$extension");
  if($res!="") return 1; else return 0;
} 
?>