<?php
$Path = dirname(__FILE__) . "/";

// --- TreeGrid.dll loading ---
$Win = strtoupper(substr(PHP_OS, 0, 3)) === 'WIN';
$LibName = $Path . "../../Server/TreeGrid." . ($Win?"dll":"so");
if (!extension_loaded('ffi')) {
   if ($Win) dl('php_ffi.dll');
   else dl('ffi.so');
   }
if (!extension_loaded('ffi')) {// Error
   echo '<Grid><IO Result="-1" Message="Error: PHP "ffi" extension is not loaded&#x0A;Copy ' . ($Win?"php_ffi.dll":"ffi.so") . ' to your php extensions directory"/></Grid>';
   exit();
   }
$TreeGrid = new ffi ("[lib='".$LibName."']
   int CreateGridA(char* Data, char* Layout, char* Defaults, char *Text, char* Bonus, char *Bonus2);
   int UpdateGridA(int Index, char* Bonus);
	int FindGridA(char *Cfg);
	void DeleteGrid(int Index);
	void Clear();
	void FreeStringA(char *String);
	char* GetBodyA(int Index, char* Cfg);
	char* GetPageA(int Index, char* Cfg);
	int SaveA(int Index, char* Input);
   int SaveExA(int Index, char* Input, int Type);
	int SaveToFileA(int Index, char* FileName, int Type);
	char* GetDataA(int Index);
   char* LastErrorA();
   char* GetLastIdA(int Index);
   char* GetChangesA(int Index, int Type);
   int FindGridsA(int* Indexes, int Max, char* Cfg, int Seconds, int Type);
   char* FindGridsStrA(int Max, char* Cfg, int Seconds, int Type);
   int LockLibraryA(char *LibName);
   int UnlockLibrary();
   ");


// --- Commandline parameters reading ---
$Function = array_key_exists("Function",$_REQUEST) ? $_REQUEST["Function"] : "";
$File = array_key_exists("File",$_REQUEST) ? $_REQUEST["File"] : "";
$Def = array_key_exists("Def",$_REQUEST) ? $_REQUEST["Def"] : "";
$Cfg = array_key_exists("Cfg",$_REQUEST) ? $_REQUEST["Cfg"] : ""; if(get_magic_quotes_gpc()) $Cfg = stripslashes($Cfg);
$Changes = array_key_exists("Changes",$_REQUEST) ? $_REQUEST["Changes"] : ""; if(get_magic_quotes_gpc()) $Changes = stripslashes($Changes);

// --- calling main function ---
switch($Function){
   case "LoadBody" : echo FuncLoadBody($File,$Def,$Cfg); break;
   case "LoadPage" : echo FuncLoadPage($Cfg); break;
   case "Save" : echo FuncSave($File,$Changes); break;
   case "CheckUpdates" : echo FuncCheckUpdates($File,$Cfg); break;
   default: Error(-3,"Error: Unknown function");
   }

// -----------------------------------------------------------------------------
function Error($num, $mess){
global $TreeGrid;
$Err = $num?$TreeGrid->LastErrorA():null;
echo '<Grid><IO Result="'.$num.'" Message="'.$mess.($Err!=null?"&#x0A;&#x0A;".htmlentities($Err):"").'"/></Grid>';
exit();
}
// -----------------------------------------------------------------------------
// Returns grid data, for Paging==3 returns only empty pages with information about their content
// Cfg contains XML with grid settings - sorting and filters
function FuncLoadBody($File,$Def,$Cfg){
global $TreeGrid, $Path, $LibName;
$Index = $TreeGrid->FindGridA($Cfg);
$TreeGrid->LockLibraryA($LibName); // Locks library to not unload after page is processed
   // !!! Library is not automatically unlocked. You should provide your own mechanism for deleting grid instances and after all instances are delete also unlock the library
if ($Index < 0) { // No instance of the grid exists
   $Ident = "<Grid><Cfg Ident='" . $File . "'/></Grid>"; // Group identification for save, uses custom TreeGrid attribute
   $IdentCount = $TreeGrid->FindGridsA(null, 1, $Ident, 0, 0);
   $CfgPaging = "<Grid><Cfg Paging='3' ChildPaging='3'/></Grid>";
   if ($IdentCount == 0) { // The first instance for saving of the grid does not exist, it will be created
      $TreeGrid->CreateGridA($Path . $File, $Path . $Def, $Path . "../../Grid/Defaults.xml", $Path . "../../Grid/Text.xml", $CfgPaging, $Ident);
      }
   $Index = $TreeGrid->CreateGridA($Path . $File, $Path . $Def, $Path . "../../Grid/Defaults.xml", $Path . "../../Grid/Text.xml", $CfgPaging, $Ident);
   }
if($Index<0) return Error(-1,"Server DLL Error: TreeGrid data not found or server has not permission to read them&#x0A;Data are located at /Examples/ServerDLL/");
$Ret = $TreeGrid->GetBodyA($Index,$Cfg);
if($Ret==null) return Error(-4,"Server DLL Error: TreeGrid data cannot be loaded");
return $Ret;
}
// -----------------------------------------------------------------------------
// Returns children of one page or one row
// Cfg contains XML with page index or row id and grid settings - sorting and filters
function FuncLoadPage($Cfg){
global $TreeGrid, $Path;
$Index = $TreeGrid->FindGridA($Cfg);
if ($Index < 0) return Error(-3, "Server DLL Error: Your temporary data have been deleted already, please reload grid!");
$Ret = $TreeGrid->GetPageA($Index,$Cfg);
if ($Ret == null) return Error(-3, "Server DLL Error: Configuration changed, you need to reload grid!"); // Unexepected error
return $Ret;
}
// -----------------------------------------------------------------------------
// Saves changed data to XML file and also to all references of this file in memory
// Changes contains XML with changed rows
// File is data file to save data to
function FuncSave($File,$Changes){
global $TreeGrid, $Path;   
$Ident = "<Grid><Cfg Ident='" . $File . "'/></Grid>"; // Group identification for save, uses custom TreeGrid attribute
$Indexes = Explode(",",$TreeGrid->FindGridsStrA(100, $Ident, 0, 0)); // Looks for all instances of the File in memory, the first instance will be saved to file, other will be updated only
$Count = count($Indexes);
if($Count==0) return Error(-3, "Server DLL Error: Your temporary data have been deleted already, you cannot save your changes any more, please reload grid!");
$Ret = $TreeGrid->SaveA($Indexes[0]-0,$Changes);
if ($Ret < 0) return Error($Ret, "Server DLL Error: Changes were not saved");
$SRet = $TreeGrid->SaveToFileA($Indexes[0]-0, $Path . $File, 0);
if ($SRet < 0) return Error($Ret, "Server DLL Error: Cannot save data to disk");
$Idx = $TreeGrid->FindGridA($Changes);
for ($i = 1; $i < $Count; $i++) $TreeGrid->SaveExA($Indexes[$i]-0, $Changes,$i==$Idx?2:1); // Updates all other instances in memory
if ($Ret > 0) return Error(0, "Warning: Not all data were successfully saved !");
$Chg = $TreeGrid->GetChangesA($Idx, 1); // Returns changes done by another user or if generated id collide with ids on server
if ($Chg == null) $Chg = "";
return "<Grid><IO Result='0'/><Cfg LastId='" + $TreeGrid->GetLastIdA($Idx) + "'/>" + $Chg + "</Grid>";
}
// -----------------------------------------------------------------------------
// Returns all updates done by other clients
// Cfg contains XML session, here is ignored
// File is data file to identify updates
function FuncCheckUpdates($File,$Cfg){
global $TreeGrid, $Path;   
$Index = $TreeGrid->FindGridA($Cfg);
if ($Index < 0) return Error(0,""); // The grid was deleted already, this is error
$Chg = $TreeGrid->GetChangesA($Index, 1);
if ($Chg != null) {
   return "<Grid><IO UpdateMessage='The data on server have been modified by another user, do you want to update your data?'/>"
      . "<Cfg LastId='" . $TreeGrid->GetLastIdA($Index) . "'/>"
      . $Chg . "</Grid>";
   }
return Error(0, "");
}
// -----------------------------------------------------------------------------
?>