<?php
/* 
----------------------------------------------------------
  MODULE : APP TOOLS AND FUNCTIONS 
  V1.0 / 2018
  AUTHOR : SGHAIER MAHMOUD  
----------------------------------------------------------
*/
/* 
---  db classes  --- 
*/
Class DbConnection {
    private  $server = "mysql:host=".db_host.";dbname=".db_database.";charset=".db_coding."";
    private  $user = db_login;
    private  $pass = db_pass;
    private  $options  = array(
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        PDO::MYSQL_ATTR_USE_BUFFERED_QUERY  
    );
    protected $con;
    public function openConnection()
          {
            try
                 {
                $this->con = new PDO($this->server, $this->user,$this->pass,$this->options);
                return $this->con;
                   }
                catch (PDOException $e)
                     { echo "There is some problem in connection: " . $e->getMessage(); exit(); }
                   }
    public function closeConnection() {
           $this->con = null;
        }
    }
/* 
---  security  --- 
*/
// verif and store posted data  
// Verify and store posted data
function verif_posted($input)
{
    $data_to_return = "";

    if (isset($_POST[$input])) {
        $data_to_return = $_POST[$input];
    }

    return trim($data_to_return);
}

// verif and get posted data  
function verif_get($input)
{
  $data_to_return = "" ;
  if (isset($_GET[$input])) 
  { $data_to_return=trim($_GET[$input]);}
  else {
    $data_to_return="";
  }
  return ($data_to_return); 
}
// verif if date format 
function is_date($date, $format = 'Y-m-d')
{
    $d = DateTime::createFromFormat($format, $date);
    // The Y ( 4 digits year ) returns TRUE for any integer with any number of digits so changing the comparison from == to === fixes the issue.
    return $d && $d->format($format) === $date;
}
// encrypt data with keypass using Open SSL ( output hex str )
function encrypt_data($data) {
  // Remove the base64 encoding from our key
  $encryption_key = base64_decode(key_salt);
  // Generate an initialization vector
  $iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length('aes-256-cbc'));
  // Encrypt the data using AES 256 encryption in CBC mode using our encryption key and initialization vector.
  $encrypted = openssl_encrypt($data, 'aes-256-cbc', $encryption_key, 0, $iv);
  // The $iv is just as important as the key for decrypting, so save it with our encrypted data using a unique separator (::)
  return strToHex(base64_encode($encrypted . '::' . $iv));
}
// dencrypt data with keypass using Open SSL ( output hex str )
function decrypt_data($data) {
  $data = hexToStr($data);
  // Remove the base64 encoding from our key
  $encryption_key = base64_decode(key_salt);
  // To decrypt, split the encrypted data from our IV - our unique separator used was "::"
  list($encrypted_data, $iv) = explode('::', base64_decode($data), 2);
  return openssl_decrypt($encrypted_data, 'aes-256-cbc', $encryption_key, 0, $iv);
}

/**
 * Encrypt PIN using XOR + Base64
 */
function encrypt_pin($pin)
{
    $key = key_salt;
    $out = '';

    for ($i = 0; $i < strlen($pin); $i++) {
        $out .= chr(ord($pin[$i]) ^ ord($key[$i % strlen($key)]));
    }

    return base64_encode($out);
}

/**
 * Decrypt PIN using XOR + Base64
 */
function decrypt_pin($encoded)
{
    $data = base64_decode($encoded);
    $key = key_salt;
    $out = '';

    for ($i = 0; $i < strlen($data); $i++) {
        $out .= chr(ord($data[$i]) ^ ord($key[$i % strlen($key)]));
    }

    return $out;
}

// strToHex conversion 
function strToHex($string){
  $hex = '';
  for ($i=0; $i<strlen($string); $i++){
      $ord = ord($string[$i]);
      $hexCode = dechex($ord);
      $hex .= substr('0'.$hexCode, -2);
  }
  return strToUpper($hex);
}

// hexToStr conversion 
function hexToStr($hex){
  $string='';
  for ($i=0; $i < strlen($hex)-1; $i+=2){
      $string .= chr(hexdec($hex[$i].$hex[$i+1]));
  }
  return $string;
}
/*
// old algorithm removed 
// decrypt data with keypass ( output str )
function encrypt_data($value){
	$text = $value;
	$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
	$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
	$crypt_text = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, key_salt, $text, MCRYPT_MODE_ECB, $iv);
	return bin2hex($crypt_text);
}
function decrypt_data($value){
	$crypt_text = fn_hex2bin($value);
	$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
	$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
	$decrypt_text = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, key_salt, $crypt_text, MCRYPT_MODE_ECB, $iv);
	return trim($decrypt_text);
}
// hex to bin str conversion 
function fn_hex2bin($h)
  {
  if (!is_string($h)) return null;
  $r='';
  for ($a=0; $a<strlen($h); $a+=2) { $r.=chr(hexdec($h{$a}.$h{($a+1)})); }
  return $r;
  }
  */
/* 
---  render errors  --- 
*/
function notify_error($prm_message) {
   echo "<notify class=\"notify-alert\">".$prm_message."</notify>"; 
}
function notify_success($prm_message) {
    echo "<notify class=\"notify-success\">".$prm_message."</notify>"; 
 }
/* 
---  grid helpers  --- 
*/
//  request and save data into session ( custom session )
function request_to_session($frmItem)
{
    global $sessionId;
    // Récupère les données actuelles de la session
    $sessionData = getSessionData($sessionId);
    if (isset($_REQUEST[$frmItem])) {
        $str = trim($_REQUEST[$frmItem]);
        $sessionData[$frmItem] = $str; // mise à jour
        storeSession($sessionId, $sessionData); // enregistre la session
    } elseif (isset($sessionData[$frmItem])) {
        $str = $sessionData[$frmItem];
    } else {
        $str = "";
    }
    return $str;
}
// store only one key sample setSession("USER_LANGUAGE", "fr");  ( custom session )
function setSession($key, $value) {
    global $sessionId;
    $sessionData = getSessionData($sessionId);
    $sessionData[$key] = $value;
    storeSession($sessionId, $sessionData);
}
//  request item->value data GET/POST 
function request_once($frmItem)
{
	if ( isset($_REQUEST[$frmItem]) ) {
		$str=trim($_REQUEST[$frmItem]);  
	}
	else { $str = "";	}
	return  $str;
}
//  request item->value data GET/POST attending multiple values
function request_once_multi($frmItem)
{
  $str = "";
	if ( isset($_REQUEST[$frmItem]) ) {
    foreach ($_REQUEST[$frmItem] as $value) {
       $str =	$str . trim($value) . ",";  
    }
	}
  else { $str = "";	}
	return  substr($str, 0, -1);  ;
}
//  view hidden inputsfor js/form/control
function view_hidden($prmmode)
{
  global $frm_arrow_state, $frm_arrow_index;
  global $table_name, $table_key,$edit_script,$edit_window;
  global $qry_id,$next_mode,$grid_script;
  if ($prmmode=="grid") { 
      echo ('<input type="hidden" name="frmarrowstate" id="frmarrowstate" value="'.$frm_arrow_state.'"/>');
      echo ('<input type="hidden" name="frmarrowindex" id="frmarrowindex" value="'.$frm_arrow_index.'"/>');
      echo ('<input type="hidden" name="actionmode" id="actionmode" value=""/>');
      echo ('<input type="hidden" name="tablename" id="tablename" value="'.$table_name.'"/>');
      echo ('<input type="hidden" name="tablekey" id="tablekey" value="'.$table_key.'"/>');
      echo ('<input type="hidden" name="editscript" id="editscript" value="'.$edit_script.'"/>');
      echo ('<input type="hidden" name="ajaxactivator" id="ajaxactivator" value="'.ajax_activator.'"/>');
      echo ('<input type="hidden" name="ajaxdelete" id="ajaxdelete" value="'.ajax_delete.'"/>');
      echo ('<input type="hidden" name="editwindow" id="editwindow" value="'.$edit_window.'"/>');
   }
   else 
   {
      echo ('<input type="hidden" name="actionmode" id="actionmode" value=""/>');
      echo ('<input type="hidden" name="frmid" id="frmid" value="'.$qry_id.'"/>'); 
      echo ('<input type="hidden" name="prmnextmode" id="prmnextmode" value="'.$next_mode.'"/>'); 
      echo ('<input type="hidden" name="editscript" id="editscript" value="'.$edit_script.'"/>');
      echo ('<input type="hidden" name="gridscript" id="gridscript" value="'.$grid_script.'"/>'); 
      echo ('<input type="hidden" name="editwindow" id="editwindow" value="'.$edit_window.'"/>');
      //echo ('<input type="hidden" name="newurl" id="newurl" value="'.$newurl.'"/>');
   }
}
// get Order By for Data Grid SQL innstruction  
function get_order_by($prmindex,$prmstate,$prmoby)
{
  $order_by_array = ( explode(",",preg_replace ("[\[|\]|\']", "", $prmoby) )) ;
  //$OrderByDwArray  = ( explode(",",preg_replace ("[\[|\]|\']", "", $prmdw) )) ;
  if ($prmindex>=0) {
    if ( $prmstate=="up" ) { $fn_order_by=$order_by_array[$prmindex]; }
    if ( $prmstate=="dw" ) { $fn_order_by=$order_by_array[$prmindex]." desc"; }
  } else { $fn_order_by = false ; }
  return $fn_order_by;
 }
// show activation bool flag from db commonly field active
function activation_status($prmstate,$prmfield)
{
  if ($prmstate==1) {
    echo '<a class="btn ico-disactivate ico-flag" data-field="'.$prmfield.'" data-toggle="tooltip" title="" data-original-title="'.DISACTIVATE_TITLE.'"><i class="fa fa-check" aria-hidden="true"></i></a>';
  } else {
    echo '<a class="btn ico-activate  ico-flag" data-field="'.$prmfield.'" data-toggle="tooltip" title="" data-original-title="'.ACTIVATE_TITLE.'"><i class="fa fa-close" aria-hidden="true"></i></a>';
  }
}
/* 
---  forms helpers  --- 
*/
//  make a dropdown values from a seperated comma list  
function drop_down($prmvalue,$prmFieldName,$prmdefaulvalues,$prmdefaultexts,$DefaultText,$prmAddAtribute,$prmDisable,$prmClass)
{
  $myarray=explode(";",$prmdefaulvalues);
  $myarraytext=explode(";",$prmdefaultexts);
  $select_str="<select name=\"".$prmFieldName."\" id=\"".$prmFieldName."\"   class=\"".$prmClass."\"";
	if ($prmAddAtribute!="")
  { $select_str=$select_str." ".$prmAddAtribute." "; }
  if ($prmDisable)
  {$select_str=$select_str." disabled ";}
  $select_str=$select_str." >";
  echo ($select_str);
  if ($DefaultText!="") {echo ("<option value=\"\">".$DefaultText."</option>");}
  for ($i=0; $i<count($myarray); $i=$i+1)
  {
    if (strtoupper($prmvalue)==strtoupper($myarray[$i]))
    {echo ("<option selected value=\"".$myarray[$i]."\">".$myarraytext[$i]."</option>");}
      else
    {
      echo ("<option value=\"".$myarray[$i]."\">".$myarraytext[$i]."</option>");
    }
  }
  echo "</select>";
  // disable make a new hidden input - ( disable inputs are not posted .!? )
  if ($prmDisable)
  {
    echo ("<input type=hidden name=\"".$prmFieldName."\" value=\"".$prmvalue."\">");
  }
}
//  make a dropdown values from sql query 
function drop_down_sql($prmInputName,$prmSQL,$prmField,$PrmKey,$prmSecondKeyValue,$DefaultText,$prmAddAtribute,$prmDisable,$prmClass)
{
  global $db; 
	$instrSql = $prmSQL;
	$select_str="<select name=\"".$prmInputName."\" id=\"".$prmInputName."\"   class=\"".$prmClass."\"";
	if ($prmAddAtribute!="")
	{ $select_str=$select_str." ".$prmAddAtribute." "; }
	if ($prmDisable)
	{ $select_str=$select_str." disabled "; }
  $select_str=$select_str." >";
	echo  $select_str;
  if ( $DefaultText != "") 
  {echo "<option selected value=\"\">".$DefaultText."</option>";}
  $SecondKeyValue =  explode(",", $prmSecondKeyValue); 
  try
  {
    foreach ($db->query($instrSql) as $row) {
      if ( in_array($row[$PrmKey], $SecondKeyValue) )
      {  echo "<option selected value=\"".$row[$PrmKey]."\">".$row[$prmField]."</option>"; }
      else 
      {  echo "<option  value=\"".$row[$PrmKey]."\">".$row[$prmField]."</option>";}
    }
  }
  catch (PDOException $e)
  {   notify_error  ( $e->getMessage()); }
	echo "</select>";
	// disable make a new hidden input - ( disable inputs are not posted  )
	if ($prmDisable)
	{		echo "<input type=hidden name=\"".$prmInputName."\" value=\"".$prmSecondKeyValue."\">"; }
}

//  make a dropdown values from sql query recursive 
function drop_down_sql_recursive(
  $prmInputName,
  $prmSQL,
  $prmField,
  $PrmParentKey,
  $prmParentKeyValue,
  $PrmKey,
  $prmKeyValue,
  $DefaultText,
  $prmAddAtribute,
  $prmDisable,
  $prmClass
) {
  global $db;

  echo "<select name=\"{$prmInputName}\" id=\"{$prmInputName}\" class=\"{$prmClass}\"";
  if ($prmAddAtribute != "") echo " {$prmAddAtribute}";
  if ($prmDisable) echo " disabled";
  echo ">";

  if ($DefaultText != "") {
    echo "<option value=\"0\">{$DefaultText}</option>";
  }

  // recursive fetch
  render_folder_options_recursive(0, $prmField, $PrmParentKey, $PrmKey, $prmKeyValue);

  echo "</select>";

  // add hidden if disabled
  if ($prmDisable) {
    echo "<input type=\"hidden\" name=\"{$prmInputName}\" value=\"{$prmKeyValue}\">";
  }
}
 
// recursive renderer
function render_folder_options_recursive($parent_id, $label_field, $parent_field, $key_field, $selected_id, $level = 0)
{
    global $db;

    // stop recursion when depth limit reached
    if ($level >= default_folder_depth) {
        return;
    }

    try {
        $stmt = $db->prepare("SELECT * FROM folders WHERE {$parent_field} = ? ORDER BY name ASC");
        $stmt->execute([$parent_id]);

        while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
            $selected = ($row[$key_field] == $selected_id) ? 'selected' : '';
            $indent = str_repeat('&nbsp;&nbsp;&nbsp;— ', $level);
            echo "<option value=\"{$row[$key_field]}\" {$selected}>{$indent}{$row[$label_field]}</option>";

            // recursion only if depth limit not reached
            if ($level + 1 < default_folder_depth ) {
                render_folder_options_recursive($row[$key_field], $label_field, $parent_field, $key_field, $selected_id, $level + 1);
            }
        }
    } catch (PDOException $e) {
        notify_error($e->getMessage());
    }
}
 
//  convert foreign key to value ( must be used with caution ) 
function fk_to_value( $prmKey,$prmKeyValue,$PrmFields,$PrmTable,$prmDefaultMessage )
{
  global $db; 
  $instrSql="SELECT ".$PrmFields." FROM ".$PrmTable." WHERE ".$prmKey."='".$prmKeyValue."' ";
  //$rs = $db->query( $instrSql )->fetchAll();
  $rs = $db->prepare($instrSql);
  $rs->execute();
  $fields_array = explode(",",$PrmFields);
  $return_value = "";
  try
  {
    if (  $row = $rs->fetch()  ) {  // tips
        do {
            foreach($fields_array as $value) {    
              $return_value =  $return_value  . $row[$value] . " "   ; 
            }
        } while ( $row  = $rs->fetch());
        return $return_value ; 
     }
     else { return $prmDefaultMessage ; }
   }
  catch (PDOException $e)
  {   notify_error  ( $e->getMessage()); }
}
//  make checkbox based on stored key/value  
function check_box($prmFieldName,$prmvalue,$prmClass)
{
 $checked = " ";	 
 if	($prmvalue==1) {$checked=" checked ";}
 echo "<input type=checkbox  class=\"".$prmClass."\"   name=\"".$prmFieldName."\" id=\"".$prmFieldName."\"  value=\"1\"  $checked>";
}
//  js redirection to avoid header sent and preserve session 
function js_redirect($prmurl)
{
echo "<script>";
echo "window.location = '".$prmurl."'";
echo "</script>";
exit();
}
/* 
---  custom forms/pages helpers  --- 
*/
// build select reason_category with options tree using recursivity for ticket view  
function reason_category_dropdown(&$output=null, $parent=0, $indent=null){
  global $db,$load_reason_fk,$load_ticket_fk,$load_selected_reason_categories;
	// select the categories that have on the parent column the value from $parent
	$stmt = $db->prepare("SELECT raison_category_id,title FROM raison_categories WHERE (reason_fk=:reasonfk and raison_category_parent_id=:parentid  and active=1 ) order by ord ");
	$stmt->execute(array(
    'parentid' 	=> $parent,
    'reasonfk' 	=> $load_reason_fk
  ));
  $stored_category_id = array();
  if ( $load_ticket_fk != "" ) {
    // check stored in db  
    $sth = $db->prepare("SELECT reason_categories_fk FROM raison_categories_by_ticket where ticket_fk = $load_ticket_fk ");
    $sth->execute();
    $stored_category_id = $sth->fetchAll(PDO::FETCH_COLUMN, 0);
    //var_dump ($stored_category_id);
  } else {
    // check filtering convert to array 
    if (strlen ($load_selected_reason_categories) >= 1 )  {
      $stored_category_id =  $fields_array = explode(",",$load_selected_reason_categories);
    }
  }
	// show the categories one by one
	while($row = $stmt->fetch(PDO::FETCH_ASSOC)){
    if (in_array($row['raison_category_id'], $stored_category_id ) ) $selected = " selected " ;
    else  $selected = " " ;
    if ($parent==0)  { 
      $output .= '<option '.$selected.'  style="font-weight:bold" value=' . $row['raison_category_id'] . '>' . $indent . $row['title'] . "</option>";
     } 
     else {
      $output .= '<option style="padding-left:30px" '.$selected.' value=' . $row['raison_category_id'] . '>' . $indent . $row['title'] . "</option>";
     } 
    if($row['raison_category_id'] != $parent){
			// in case the current category's id is different that $parent
			// we call our function again with new parameters
			reason_category_dropdown($output, $row['raison_category_id'], $indent . '');
		}
	}
	// return the list of categories
	return $output;
}
// build select reason_category with options tree using recursivity for general view 
// to Enhance ( using table keys parms ) 
function drop_down_tree($prmInputName,$prmKeyValue,$fkParentKeyValue,$prmAttributes,$DefaultText,$prmClass,$prmTopRootText,$maxLevel)
{
  global $db; 
  $selectstr="<select  name=\"".$prmInputName."\" ".$prmAttributes." id=\"".$prmInputName."\" class=\"".$prmClass."\">";
  echo  $selectstr;
  if ( $DefaultText != "") { echo "<option selected value=\"\">".$DefaultText."</option>";}
  // handle root parent
   if ($fkParentKeyValue==0 ) { $strSelectedAtributeRoot = "selected" ; }
  	   else {  $strSelectedAtributeRoot = "";  }	   
    if ($prmTopRootText!="") {
	    echo '<option '.$strSelectedAtributeRoot.' value="0">';
	    echo $prmTopRootText; 
	    echo '</option>';
	   }
show_tree_options(0,0,$prmKeyValue,$fkParentKeyValue,$maxLevel);
echo "</select>";
}
// build Select with options tree using recursivity ( internal )  //
// $parent is the parent of the children we want to see
// $level is increased when we go deeper into the tree, used to display a nice indented tree
function show_tree_options($parent, $level,$prmKeyValue,$fkParentKeyValue,$maxLevel) {
   global $db; 
   $strSelectedAtribute = "";
   $stmt = $db->prepare("SELECT title,raison_category_id,raison_category_parent_id,reason_fk FROM raison_categories where	raison_category_parent_id = :parent order by ord  ");
   //$stmt->bindParam(':parent', $parent, PDO::PARAM_INT);
   $stmt->execute(array(':parent' => $parent));
   // display each child
   while($row = $stmt->fetch(PDO::FETCH_ASSOC)){
   	 // $children++;
     // if ($row["raison_category_id"]==$prmKeyValue) { $strSelectedAtribute = "selected" ; }
     // We are interested to match the parent of the item not the fk
     if ($row["raison_category_id"]==$fkParentKeyValue) { $strSelectedAtribute = "selected" ; }
     else {  $strSelectedAtribute = "";  } 
	   echo '<option '.$strSelectedAtribute.' data-fk-filter = "'.$row["reason_fk"].'"  value="'.$row["raison_category_id"].'">';
	   echo str_repeat("-", (($level+1)*4)) ." ".$row['title']; 
     echo '</option>';
     if (  ($level+1) <= $maxLevel  ) { 
       // call this function again to display this child's children
       show_tree_options($row['raison_category_id'], $level+1,$prmKeyValue,$fkParentKeyValue,$maxLevel);
     }
   }
}

/* 
--- file size   --- 
*/
function formatFileSize($bytes)
{
    if ($bytes < 1024) {
        return $bytes . ' o';
    } elseif ($bytes < 1048576) {
        return round($bytes / 1024, 2) . ' Ko';
    } elseif ($bytes < 1073741824) {
        return round($bytes / 1048576, 2) . ' Mo';
    } else {
        return round($bytes / 1073741824, 2) . ' Go';
    }
}


?>