<?php

include_once('Database.php');

class UpdateManager
{
  var $Revision;
  var $Trace;
  var $VersionTable;
  /* @var Database */
  var $Database;
  var $InstallMethod;
  
  function __construct()
  {
	  $this->Revision = 0;
	  $this->Trace = array();
	  $this->VersionTable = 'SystemVersion';
	  $this->InstallMethod = 'FullInstall';
	  $this->InsertSampleDataMethod = 'InsertSampleData';
  }
  
  function GetDbVersion()
  {
	  $DbResult = $this->Database->select($this->VersionTable, '*', 'Id=1');
	  $Version = $DbResult->fetch_assoc();	 
    return($Version['Revision']);
  }
  
  function IsInstalled()
  {	 
	  $DbResult = $this->Database->query('SHOW TABLES LIKE "'.$this->VersionTable.'"');
    return($DbResult->num_rows > 0);    
  }

  function IsUpToDate()
  {
	  return($this->Revision <= $this->GetDbVersion());
  }
  
  function Update()
  {
	  $DbRevision = $this->GetDbVersion();
  	$Output = 'Počáteční revize databáze: '.$DbRevision.'<br/>'; 
	  while($this->Revision > $DbRevision)
    {
	    $TraceItem = $this->Trace[$DbRevision];
	    $Output .= 'Aktualizace na verzi: '.$TraceItem['Revision'].'<br/>';	    
	    $RevUpdate = $TraceItem['Function'];	  
	    $RevUpdate($this);
 	    $DbRevision = $TraceItem['Revision'];
 	    $this->Database->query('UPDATE `'.$this->VersionTable.'` SET `Revision`= '.$TraceItem['Revision'].' WHERE `Id`=1');
	  }
	  return($Output);	 
  }
  
  function Install()
  {  	
  	$InstallMethod = $this->InstallMethod; 
  	$InstallMethod($this);
  }
  
  function Uninstall()
  {
    
  }
  
  function InsertSampleData()
  {  	
  	$InstallMethod = $this->InsertSampleDataMethod; 
  	$InstallMethod($this);
  }
  
  function Execute($Query)
  {
	  echo($Query.';<br/>');
	  flush();
	  return($this->Database->query($Query));
  }
}

class UpdateInterface
{
  var $UpdateManager;
  var $ConfigDefinition;
  var $Config;
  var $DatabaseRevision;
  var $Revision;
  var $Updates;
  
  function __construct()
  {
  }
  
  function LoginPanel()
  {
	  $Output = '<h3>Přihlášení k instalaci</h3>'.
	    '<form action="" method="post">'.
		  '<table>'.
			'<tr><td>Systémové heslo:</td><td> <input type="password" name="SystemPassword" value=""/></td></tr>'.
			'</table>'.
			'<input type="submit" name="login" value="Přihlásit"/>'.
	  	'</form>';	
  	return($Output);
  }
  
  function ControlPanel()
  {
    $YesNo = array(false => 'Ne', true => 'Ano');
    $Output = '<h3>Správa instance</h3>'.
      'Je instalováno: '.$YesNo[$this->UpdateManager->IsInstalled()].'<br/>';
    if($this->UpdateManager->IsInstalled())
      $Output .= 'Je aktuální: '.$YesNo[$this->UpdateManager->IsUpToDate()].'<br/>'.
      'Verze databáze: '.$this->UpdateManager->GetDbVersion().'<br/>';
    $Output .= 'Verze databáze kódu: '.$this->UpdateManager->Revision.'<br/>'.
      '<form action="" method="post">';
    if($this->UpdateManager->IsInstalled())
    {
      if(!$this->UpdateManager->IsUpToDate())
        $Output .= '<input type="submit" name="update" value="Aktualizovat"/> ';
      $Output .= '<input type="submit" name="insert_sample_data" value="Vložit vzorová data"/> ';
      $Output .= '<input type="submit" name="uninstall" value="Odinstalovat"/> ';
    } else $Output .= '<input type="submit" name="install" value="Instalovat"/> ';
    $Output .= '<input type="submit" name="configure" value="Nastavit"/> ';
    $Output .= '<input type="submit" name="logout" value="Odhlásit"/> ';
    $Output .= '</form>';
    return($Output);
  }
  
  function Show()
  {
    $Output = '<?xml version="1.0" encoding="utf-8"?>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="cz">'.
    '<head>'.
    '<meta http-equiv="content-type" content="application/xhtml+xml; charset=utf-8" />'.
    '<title>Správa instance</title>'.
    '</head><body>';
    if(isset($this->Config))
    {
      if(!array_key_exists('SystemPassword', $_SESSION)) $_SESSION['SystemPassword'] = '';
      if(array_key_exists('login', $_POST)) $_SESSION['SystemPassword'] = $_POST['SystemPassword'];
      if(sha1($_SESSION['SystemPassword']) != $this->Config['SystemPassword'])
      {
        $Output .= $this->LoginPanel();
      } else
      {
        date_default_timezone_set('Europe/Prague');
        // SQL injection hack protection
        foreach($_POST as $Index => $Item) $_POST[$Index] = addslashes($Item);
        foreach($_GET as $Index => $Item) $_GET[$Index] = addslashes($Item);
    
        if(isset($_SERVER['REMOTE_ADDR'])) session_start();
    
        $Database = new Database();
        $Database->Connect($this->Config['Database']['Host'], $this->Config['Database']['User'], 
           $this->Config['Database']['Password'], $this->Config['Database']['Database']);
        $Database->Prefix = $this->Config['Database']['Prefix'];
        $Database->charset($this->Config['Database']['Charset']);
        $Database->ShowSQLError = $this->Config['Web']['ShowSQLError'];
        $Database->ShowSQLQuery = $this->Config['Web']['ShowSQLQuery'];
    
        $this->UpdateManager = new UpdateManager();
        $this->UpdateManager->Database = $Database;
        $this->UpdateManager->Revision = $this->DatabaseRevision;
        $this->UpdateManager->Trace = $this->Updates;
        $this->UpdateManager->InstallMethod = 'FullInstall';
    
        if(array_key_exists('logout', $_POST))
        {
          $_SESSION['SystemPassword'] = '';
          $Output .= 'Odhlášen';
          $Output .= $this->LoginPanel();
        } else
        if(array_key_exists('update', $_POST))
        {
          $Output .= '<h3>Aktualizace</h3>';
          $Output .= $this->UpdateManager->Update();
          $Output .= $this->ControlPanel();
        } else
        if(array_key_exists('install', $_POST))
        {
          $Output .= '<h3>Instalace</h3>';
          $this->UpdateManager->Install();
          $Output .= $this->UpdateManager->Update();
          $Output .= $this->ControlPanel();
        } else
        if(array_key_exists('uninstall', $_POST))
        {
          $Output .= '<h3>Odinstalace</h3>';
          $this->UpdateManager->Uninstall();
          $Output .= $this->ControlPanel();
        } else
        if(array_key_exists('insert_sample_data', $_POST))
        {
          $Output .= '<h3>Vložení vzorových dat</h3>';
          $this->UpdateManager->InsertSampleData();
          $Output .= $this->ControlPanel();
        } else
        if(array_key_exists('configure_save', $_POST))
        {
          $Output .= $this->ConfigSave($this->Config);
          $Output .= $this->ControlPanel();
        } else
        if(array_key_exists('configure', $_POST))
        {
          $Output .= $this->PrepareConfig($this->Config);
        } else
        {
          $Output .= $this->ControlPanel();
        }
      }
    } else
    {
      if(array_key_exists('configure_save', $_POST))
      {
        $Output .= $this->ConfigSave(array());
        $Output .= 'Pokračujte k přihlášení <a href="">zde</a>';
      } else {
        $Output .= $this->PrepareConfig(array());
      }
    }
    $Output .= '</body></html>';
    echo($Output);
  }
  
  function PrepareConfig($Config)
  {
    $Output = '';
    if(!file_exists('../config.php') and !is_writable('..'))
      $Output .= 'Varování: Konfigurační soubor nebude možné zapsat, protože složka není povolená pro zápis!';
    if(file_exists('../config.php') and !is_writable('../config.php'))
      $Output .= 'Varování: Konfigurační soubor nebude možné zapsat, protože soubor config.php není povolen pro zápis!';
    $Output .= '<h3>Nastavení systému</h3>'.
        '<form action="" method="post">'.
        '<table>';
    foreach($this->ConfigDefinition as $Def)
    {
      $PathParts = explode('/', $Def['Name']);
      $TempConfig = &$Config;
      foreach($PathParts as $Part)
      if(array_key_exists($Part, $TempConfig))
      {
        $TempConfig = &$TempConfig[$Part];
      }
      if(!is_array($TempConfig)) $Value = $TempConfig;
        else $Value = $Def['Default'];
      $Output .= '<tr><td>'.$Def['Title'].'</td><td>';
      if($Def['Type'] == 'String') $Output .= '<input type="text" name="'.$Def['Name'].'" value="'.$Value.'"/>';
      if($Def['Type'] == 'Password') $Output .= '<input type="password" name="'.$Def['Name'].'"/>';
      if($Def['Type'] == 'Integer') $Output .= '<input type="text" name="'.$Def['Name'].'" value="'.$Value.'"/>';
      if($Def['Type'] == 'Boolean') $Output .= '<input type="text" name="'.$Def['Name'].'" value="'.$Value.'"/>';
    }
    $Output .= '</td></tr>'.
      '<tr><td colspan="2"><input type="submit" name="configure_save" value="Nastavit"/></td></tr>'.
      '</table>'.
      '</form>';
    return($Output);
  }
  
  function ConfigSave($DefaultConfig)
  {
    $Config = $DefaultConfig;
    foreach($this->ConfigDefinition as $Def)
    { 
      $Value = null;    
      if($Def['Type'] == 'String') if(array_key_exists($Def['Name'], $_POST))
        $Value = $_POST[$Def['Name']];
      if($Def['Type'] == 'Password') if(array_key_exists($Def['Name'], $_POST) and ($_POST[$Def['Name']] != ''))
        $Value = $_POST[$Def['Name']];
      if($Def['Type'] == 'Integer') if(array_key_exists($Def['Name'], $_POST))
        $Value = $_POST[$Def['Name']];
      if($Def['Type'] == 'Boolean') if(array_key_exists($Def['Name'], $_POST))
        $Value = $_POST[$Def['Name']];
      if(!is_null($Value))
      {
        $PathParts = explode('/', $Def['Name']);
        $TempConfig = &$Config;
        foreach($PathParts as $Part)
        {
          $TempConfig = &$TempConfig[$Part];
        }
        if(!is_array($TempConfig)) $TempConfig = $Value;
          else $Value = $Def['Default'];
        }
      }
    $ConfigText = $this->CreateConfig($Config);
    file_put_contents('../config.php', $ConfigText);
    $Output .= 'Konfigurace nastavena<br/>';
    return($Output);
  }
  
  function CreateConfig($Config)
  {
  
    $Output = "<?php\n\n".  
    "\$IsDeveloper = in_array(\$_SERVER['REMOTE_ADDR'], array('127.0.0.1'));\n\n";
  
    foreach($this->ConfigDefinition as $Def)
    {
      $PathParts = explode('/', $Def['Name']);
      $Output .= "\$Config";
      foreach($PathParts as $Part)
        $Output .= "['".$Part."']";
      $TempConfig = &$Config;
      foreach($PathParts as $Part)
      if(array_key_exists($Part, $TempConfig))
      {
        $TempConfig = &$TempConfig[$Part];
      }
      if(!is_array($TempConfig)) $Value = $TempConfig;
        else $Value = $Def['Default'];
      $Output .= " = '".$Value."';\n";
    }
    $Output .= "\n\n?>";
    return($Output);
  }  
}

?>
