<?php

define('FT_OPTION', 1); // option formatter

class clsItemDB 
{ 
  var $Formatters = Array(); //  by Alex
  var $m_dirtyFieldsMap = array();
  var $Data = array();
  var $adodbConnection;
  var $tablename;
  var $BasePermission;
  var $id_field;
  var $NoResourceId;
  var $debuglevel;

  var $SelectSQL = 'SELECT * FROM %s WHERE %s';
  
  function clsItemDB()
  {
      $this->adodbConnection = &GetADODBConnection();
      $this->tablename="";
      $this->NoResourceId=0;  
      $this->debuglevel=0;
  }
  
  // ============================================================================================
  function GetFormatter($field)
  {
  	return $this->HasFormatter($field) ? $this->Formatters[$field] : false;
  }
  
  function SetFormatter($field, $type, $params)
  {
  	// by Alex
  	// all params after 2nd are formmater type specific
  	$this->Formatters[$field]['type'] = $type;
  	switch($type)
  	{
  		case FT_OPTION:
  			$this->Formatters[$field]['options'] = $params;
  			break;	
  	}
  }
  /*	
  function FormatFields()
  {
	// format item in list data before printing
	
	foreach($this->Formatters as $field => $formatter)
		$this->Data[$field] = $this->FormatField($field);
  }
  */
  function FormatField($field)
  {
  	// formats single field if it has formatter
  	if( $this->HasFormatter($field) )
  	{
  		$fmt = $this->Formatters[$field];
  		switch($fmt['type'])
		{
			case FT_OPTION:
				return $fmt['options'][ $this->Data[$field] ];
				break;	
		}
  	}
  	else
  		return $this->Get($field);
  }
  
  function HasFormatter($field)
  {
  	// checks if formatter is set for field
  	return isset($this->Formatters[$field]) ? 1 : 0;
  }
  // ============================================================================================
  
  function UnsetIdField()
  {
    $f = $this->IdField();
    unset($this->Data[$f]);
    unset($this->m_dirtyFieldsMap[$f]);
  }

  function UnsetField($field)
  {
      unset($this->Data[$field]);
      unset($this->m_dirtyFieldsMap[$field]);
  }

  function IdField()
  {
      if(!strlen($this->id_field))
      {      
        return $this->tablename."Id";
      }
      else
          return $this->id_field;
  }

  function UniqueId()
  {
      return $this->Get($this->IdField());
  }

  function SetUniqueId($value)
  {
      $var = $this->IdField();	  
      $this->Set($var, $value);
  }

  function SetModified($UserId=NULL)
  {
      global $objSession;
      
      $keys = array_keys($this->Data);
      if(in_array("Modified",$keys))
      {
          $this->Set("Modified",adodb_date("U"));
      }
      if(in_array("ModifiedById",$keys))
      {
          if(!$UserId)
              $UserId = $objSession->Get("PortalUserId");
          $this->Set("ModifiedById",$UserId);
      }
  }

  function PrintVars()
  {
      echo '<pre>'.print_r($this->Data, true).'</pre>';
  }
  
// =================================================================
  function GetFormatted($name)
  {	
      // get formatted field value
      return $this->FormatField($name);
  }

  function Get($name)
  {	
      // get un-formatted field value
      //if( !isset($this->Data[$name]) ) print_pre( debug_backtrace() );
      return $this->HasField($name) ? $this->Data[$name] : '';
  }
// =================================================================

	function HasField($name)
	{
		// checks if field exists in item
		return isset($this->Data[$name]) ? 1 : 0;	
	}
	
	function Set($name, $value)
  	{	
		//echo "Setting Field <b>$name</b>: = [$value]<br>";
		if( is_array($name) )
      	{
          	for ($i=0; $i < sizeof($name); $i++)
          	{	
          		$var = "m_" . $name[$i];
              	if( !$this->HasField($name[$i]) || ($this->Data[$name[$i]] != $value[$i]))
              	{
              		$this->Data[$name[$i]] = $value[$i];
              		$this->m_dirtyFieldsMap[$name[$i]] = $value[$i];
            	}
          	}
      	}
      	else
      	{
       		$var = "m_" . $name;
       		if( !$this->HasField($name) || $this->Data[$name] != $value )
       		{
       			$this->Data[$name] = $value;
       			$this->m_dirtyFieldsMap[$name] = $value;
    		}
      	}
  	} 

  function Dirty($list=NULL)
  {
      if($list==NULL)
      {
        foreach($this->Data as $field => $value)
        {
        	$this->m_dirtyFieldsMap[$field] = $value;
        }
      }
      else
      {      
        foreach($list as $field) 
        {	
       		$this->m_dirtyFieldsMap[$field] = $this->Data[$field];
        }
      }
  }

  function Clean($list=NULL)
  {
      if($list == NULL)
      {
          unset($this->m_dirtyFieldsMap);
          $this->m_dirtyFieldsMap=array();
      }
      else
      {      
        foreach($list as $value) 
        {	
          $varname = "m_" . $value;
          unset($this->m_dirtyFieldsMap[$value]);
        }
      }
  }

  function SetDebugLevel($value)
  {
      $this->debuglevel = $value;
  }

  function SetFromArray($data, $dirty = false)
  { 
      if(is_array($data))
      {      
        $this->Data = $data;
        if($dirty) $this->m_dirtyFieldsMap = $data;
      }
  }

  function GetData()
  {
    return $this->Data;
  }

  function SetData($data, $dirty = false)
  {
      $this->SetFromArray($data, $dirty);
  }

  function Delete()
  { 
      global $Errors;

      if($this->Get($this->IdField())==0)
      {
          $Errors->AddError("error.AppError",NULL,'Internal error: Delete requires set id',"",get_class($this),"Delete");
          return false;
      }

      $sql = sprintf('DELETE FROM %s WHERE %s = %s', $this->tablename, $this->IdField(),
                      $this->UniqueId());
      if($this->debuglevel>0)
        echo $sql."<br>";
      if ($this->adodbConnection->Execute($sql) === false)
      {
          $Errors->AddError("error.DatabaseError",NULL,$this->adodbConnection->ErrorMsg(),"",get_class($this),"Delete");
          return false;
      }
      return true;
  }

  function Update($UpdatedBy=NULL)
  {
      global $Errors, $objSession;
		
      if(count($this->m_dirtyFieldsMap) == 0)
          return true;

      $this->SetModified($UpdatedBy);
      $sql = "UPDATE ".$this->tablename ." SET ";
      $first  = 1;
      
      foreach ($this->m_dirtyFieldsMap as $key => $value)
      {
          if(!is_numeric($key) && $key != $this->IdField())
          {          
            if($first)
            {
              $sql = sprintf("%s %s=%s",$sql,$key,$this->adodbConnection->qstr(stripslashes($value)));
              $first = 0;
            }
            else
            {
              $sql = sprintf("%s, %s=%s",$sql,$key,$this->adodbConnection->qstr(stripslashes($value)));
            }
          }
          if (!(($value == '' || $value == 0) && ($this->Data[$key] == 'NULL' || $this->Data[$key] == '0' || $this->Data[$key] == ''))) {
          	if (!strstr($key, 'Modif') && $key != 'CreatedOn') {
          		$objSession->SetVariable("HasChanges", 1);
        	}
          }  	
      }

      $sql = sprintf("%s WHERE %s = '%s'",$sql, $this->IdField(), $this->UniqueId());

     if($this->debuglevel>0)
          echo $sql."<br>";
      if ($this->adodbConnection->Execute($sql) === false)
      {
          $Errors->AddError("error.DatabaseError",NULL,$this->adodbConnection->ErrorMsg(),"",get_class($this),"Update");
          return false;
      }
      
/*      if ($this->adodbConnection->Affected_Rows() > 0) {
      	$objSession->SetVariable("HasChanges", 1);
  	  }*/
      
      return true;
  }
	
	function ReplaceID($new_id)
	{
		// replace item's id, because Update method 
		// is too dummy to do this autommatically
		// USED in temporary table editing stuff
		$db =& $this->adodbConnection;
		$sql = "UPDATE %1\$s SET `%2\$s` = %3\$s WHERE `%2\$s` = %4\$s"; 
		$sql = sprintf($sql, $this->tablename, $this->IdField(), $new_id, (int)$this->UniqueId() );
		if($this->debuglevel > 0) echo $sql.'<br>';
		$db->Execute($sql);
	}
	
  function CreateSQL()
  {
  	 global $Errors;
  	 
     $sql = "INSERT INTO ".$this->tablename." (";
     $first  = 1;
     foreach ($this->Data as $key => $value)
     {
          if($first)
          {
              $sql = sprintf("%s %s",$sql,$key);
              $first = 0;
          }
          else
          {
              $sql = sprintf("%s, %s",$sql,$key);
          }
     }
     $sql = sprintf('%s ) VALUES (',$sql);
     $first = 1;
     foreach ($this->Data as $key => $value)
     {
     	if( is_array($value) )
     	{
     		echo "Invalid Value: ";
     		print_pre($value);
     		echo "Tracing:<br>";
     		trace();
     		die();
     	}
     	if($first)
     	{
     		$sql = sprintf("%s %s",$sql,$this->adodbConnection->qstr(stripslashes($value)));
     		$first = 0;
     	}
     	else
     	{
     		$sql = sprintf("%s, %s",$sql,$this->adodbConnection->qstr(stripslashes($value)));
     	}
     }
     $sql = sprintf('%s)',$sql);
     
  	return $sql;
  }
  
  function Create()
  {
     global $Errors, $objSession;
     
	if($this->debuglevel) echo "Creating Item: ".get_class($this)."<br>";
     if($this->NoResourceId!=1 && (int)$this->Get("ResourceId")==0)
     {
        $this->Set("ResourceId", GetNextResourceId());
     }
     $sql = $this->CreateSql();
     
     if($this->debuglevel>0)
        echo $sql."<br>\n";

     if ($this->adodbConnection->Execute($sql) === false)
      {  
          $Errors->AddError("error.DatabaseError",NULL,$this->adodbConnection->ErrorMsg(),"",get_class($this),"Create");
          return false;
      }

      $this->SetUniqueId($this->adodbConnection->Insert_ID());
      
      
      if ($this->adodbConnection->Affected_Rows() > 0) {
      	$objSession->SetVariable("HasChanges", 1);
  	  }      
      
      return true;
  }

  function Increment($field)
  {	    
      global $Errors;

      $sql = "Update ".$this->tablename." set $field=$field+1 where ".$this->IdField()."=" . $this->UniqueId();
      if($this->debuglevel>0)
          echo $sql."<br>";
      $result = $this->adodbConnection->Execute($sql);
      if ($result === false)
      {
          $Errors->AddError("error.DatabaseError",NULL,$this->adodbConnection->ErrorMsg(),"",get_class($this),"Increment");
          return false;
      }
      $this->Set($field,$this->Get($field)+1);
  }

  function Decrement($field)
  {	
      global $Errors;

      $sql = "Update ".$this->tablename." set $field=$field-1 where ".$this->IdField()."=" . $this->UniqueId();
      if($this->debuglevel>0)
          echo $sql;
      $result = $this->adodbConnection->Execute($sql);
      if ($result === false)
      {
          $Errors->AddError("error.DatabaseError",NULL,$this->adodbConnection->ErrorMsg(),"",get_class($this),"Decrement");
          return false;
      }
      $this->Set($field,$this->Get($field)-1);
  }
  
  function GetFieldList($UseLoadedData=FALSE)
  {
  	if(count($this->Data) && $UseLoadedData==TRUE)
  	{
  		$res = array_keys($this->Data);
  	}
  	else
  	{
  		$res = $this->adodbConnection->MetaColumnNames($this->tablename);
  	}
  	return $res;
  }
  
  function UsingTempTable()
  {
  	global $objSession;
  	
  	$temp = $objSession->GetEditTable($this->tablename);
  	$p = GetTablePrefix()."ses";
  	$t = substr($temp,0,strlen($p));
  	$ThisTable = substr($this->tablename,0,strlen($p));  	
  	if($t==$ThisTable)
  	{
  		return TRUE;
  	}
  	else
  	  return FALSE;
  }
  
    function LoadFromDatabase($Id, $IdField = null) // custom IdField by Alex
    {
		global $objSession,$Errors;
       
        if(!isset($Id))
        {
            $Errors->AddError("error.AppError",NULL,'Internal error: LoadFromDatabase id',"",get_class($this),"LoadFromDatabase");
            return false;
        }
       
       // --------- multiple ids allowed: begin -----------------
       $id_field = isset($IdField) ? $IdField : $this->IdField();
       if( !is_array($id_field) ) $id_field = Array($id_field);
       if( !is_array($Id) ) $Id = Array($Id);
       
       $i = 0; $id_count = count($id_field);
       $conditions = Array();
       while($i < $id_count)
       {
       		$conditions[] = "(`".$id_field[$i]."` = '".$Id[$i]."')";
       		$i++;
       }
       $sql = sprintf($this->SelectSQL, $this->tablename, implode(' AND ', $conditions) );
       // --------- multiple ids allowed: end --------------------
       if($this->debuglevel) echo "Load SQL: $sql<br>"; 
        $result = $this->adodbConnection->Execute($sql);
        if ($result === false)
        {
            $Errors->AddError("error.DatabaseError",NULL,$this->adodbConnection->ErrorMsg(),"",get_class($this),"LoadFromDatabase");
            return false;
        }
        $data = $result->fields;
		if($this->debuglevel) print_pre($data);
		if(is_array($data))
          $this->SetFromArray($data);
        $this->Clean();
        return TRUE;
    }
    
    function FieldExists($field)
    {
      $res = array_key_exists($field,$this->Data);
      return $res;	
    }
  
    function ValueExists($Field,$Value)
    {
    	$sql = "SELECT $Field FROM ".$this->tablename." WHERE $Field='$Value'";
    	$rs = $this->adodbConnection->Execute($sql);
    	if($rs && !$rs->EOF)
    	{
    		return TRUE;
    	}
    	else
    	  return FALSE;
    }

    function FieldMax($Field)
    {
    	$sql = "SELECT Max($Field) as m FROM ".$this->tablename;
    	$rs = $this->adodbConnection->Execute($sql);
    	if($rs && !$rs->EOF)
    	{
    		$ret = $rs->fields["m"];
    	}
    	else
    	  $ret = 0;
    }
    
    function FieldMin($Field)
    {
    	$sql = "SELECT Min($Field) as m FROM ".$this->tablename;
    	$rs = $this->adodbConnection->Execute($sql);
    	if($rs && !$rs->EOF)
    	{
    		$ret = $rs->fields["m"];
    	}
    	else
    	  $ret = 0;
    }
    
    function TableExists($table = null)
    {
    	// checks if table specified in item exists in db	
    	$db =& $this->adodbConnection;
    	$sql = "SHOW TABLES LIKE '%s'";
    	if($table == null) $table = $this->tablename;
    	$rs = $db->Execute( sprintf($sql, $table) );
    	
    	if( $rs->RecordCount() == 1 ) // table exists in normal case
    		return 1;
    	else // check if table exists in lowercase
    		$rs = $db->Execute( sprintf($sql, strtolower($table) ) );
    	
    	return ($rs->RecordCount() == 1) ? 1 : 0;
    }	
    	
}
?>