<?php

include_once(dirname(__FILE__).'/Update.php');
include_once(dirname(__FILE__).'/DefaultConfig.php');
include_once(dirname(__FILE__).'/FullInstall.php');
include_once(dirname(__FILE__).'/Updates.php');

class PageSetup extends Page
{
  var $UpdateManager;
  var $ConfigDefinition;
  var $Config;
  var $DatabaseRevision;
  var $Revision;
  var $Updates;
  var $ConfigDir;
  
  function __construct($System)
  {
    parent::__construct($System);
    $this->FullTitle = 'Instalace aplikace';
    $this->ShortTitle = 'Instalátor';
    //$this->ParentClass = 'PagePortal';
    $this->ConfigDir = dirname(__FILE__).'/../..';
  }
  
  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()
  {
    global $YesNo;
    $Output = '';
  
    $Output .= 'Je připojení k databázi: '.$YesNo[$this->UpdateManager->Database->Connected()].'<br/>';
    if($this->UpdateManager->Database->Connected())
    {
      $Output .= '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/>';
      if($this->UpdateManager->IsInstalled())
      {
        if(!$this->UpdateManager->IsUpToDate())
          $Output .= '<a href="?action=upgrade">Povýšit</a> ';
        $Output .= '<a href="?action=insert_sample_data">Vložit vzorová data</a> ';
        $Output .= '<a href="?action=reload_modules">Obnovit seznam modulů</a> ';
        $Output .= '<a href="?action=uninstall">Odinstalovat</a> ';
        $Output .= '<a href="?action=modules">Správa modulů</a> ';
      } else $Output .= '<a href="?action=install">Instalovat</a> ';
    }
    $Output .= '<a href="?action=configure">Nastavit</a> ';
    $Output .= '<a href="?action=logout">Odhlásit</a> ';
    $Output .= '';
    return($Output);
  }
  
  function Show()
  {
	  global $ConfigDefinition, $DatabaseRevision, $Config, $Updates;
	  
	  $this->UpdateManager = $this->System->Setup->UpdateManager;
	  $DefaultConfig = new DefaultConfig();
	  $this->ConfigDefinition = $DefaultConfig->Get();
	  $this->DatabaseRevision = $DatabaseRevision;
	  $this->Config = &$Config; 

	  $Output = '';
    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
      {  
        if(array_key_exists('action', $_GET)) $Action = $_GET['action'];
          else $Action = '';
        if($Action == 'logout')
        {
          $_SESSION['SystemPassword'] = '';
          $Output .= 'Odhlášen';
          $Output .= $this->LoginPanel();
        } else
        if($Action == 'upgrade')
        {
          $Output .= '<h3>Povýšení</h3>';
          try {	  
            $Output .= $this->System->Setup->Upgrade();
          } catch (Exception $E) {
	          $Output .= $this->SystemMessage('Chyba aktualizace', 'Došlo k chybě v SQL dotazu při aktualizaci: <br/>'.$E->getMessage());
     	    }
 	        $Output .= $this->ControlPanel();
        } else
        if($Action == 'install')
        {
          $Output .= '<h3>Instalace</h3>';
          $this->System->Setup->Install();
          $this->System->ModuleManager->LoadModules();
          $this->System->ModuleManager->SaveState();
          //$Output .= $this->System->Setup->Upgrade();
          $Output .= $this->ControlPanel();
        } else
        if($Action == 'uninstall')
        {
          $Output .= '<h3>Odinstalace</h3>';
          $this->System->Setup->Uninstall();
          $Output .= $this->ControlPanel();
        } else
        if($Action == 'reload_modules')
        {
          $Output .= '<h3>Znovunačtení seznamu modulů</h3>';
          $this->System->ModuleManager->LoadModules();
          $this->System->ModuleManager->SaveState();
          $Output .= $this->ControlPanel();
        } else
        if($Action == 'insert_sample_data')
        {
          $Output .= '<h3>Vložení vzorových dat</h3>';
          $this->System->Setup->InsertSampleData();
          $Output .= $this->ControlPanel();
        } else
        if($Action == 'modules')
        {
          $Output .= $this->ShowModules();  
        } else
        if($Action == 'configure_save')
        {
           $Output .= $this->ConfigSave($this->Config);
           $Output .= $this->ControlPanel();
        } else
        if($Action == 'configure')
        {
          $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());
      }
    }
    return($Output);
  }
  
  function ShowModules()
  {
    $Output = '';
    if(array_key_exists('op', $_GET)) $Operation = $_GET['op'];
      else $Operation = '';
    if($Operation == 'install')
    {
      $this->System->ModuleManager->Modules[$_GET['name']]->Install();
      $this->System->ModuleManager->SaveState();
      $Output .= 'Modul '.$_GET['name'].' instalován<br/>';
    } else
    if($Operation == 'uninstall')
    {
      $this->System->ModuleManager->Modules[$_GET['name']]->Uninstall();
      $this->System->ModuleManager->SaveState();
      $Output .= 'Modul '.$_GET['name'].' odinstalován<br/>';
    } else
    if($Operation == 'enable')
    {
      $this->System->ModuleManager->Modules[$_GET['name']]->Enable();
      $this->System->ModuleManager->SaveState();
      $Output .= 'Modul '.$_GET['name'].' povolen<br/>';
    } else
    if($Operation == 'disable')
    {
      $this->System->ModuleManager->Modules[$_GET['name']]->Disable();
      $this->System->ModuleManager->SaveState();
      $Output .= 'Modul '.$_GET['name'].' zakázán<br/>';
    } else
    if($Operation == 'upgrade')
    {
      $this->System->ModuleManager->Modules[$_GET['name']]->Upgrade();
      $this->System->ModuleManager->SaveState();
      $Output .= 'Modul '.$_GET['name'].' povýšen<br/>';
    }
    $Output .= '<h3>Správa modulů</h3>';
    $Output .= $this->ShowList();
    return($Output);
  }
  
  function ShowList()
  {
    global $YesNo;
    
    $Output = '';
    $PageList = GetPageList(count($this->System->ModuleManager->Modules));
  
    $Output .= $PageList['Output'];
    $Output .= '<table class="WideTable" style="font-size: small;">';
     
    $TableColumns = array(
        array('Name' => 'Name', 'Title' => 'Jméno'),
        array('Name' => 'Creator', 'Title' => 'Tvůrce'),
        array('Name' => 'Version', 'Title' => 'Verze'),
        array('Name' => 'License', 'Title' => 'Licence'),
        array('Name' => 'Installed', 'Title' => 'Instalováno'),
        array('Name' => 'Enabled', 'Title' => 'Povoleno'),
        array('Name' => 'Description', 'Title' => 'Popis'),
        array('Name' => 'Dependencies', 'Title' => 'Závislosti'),
        array('Name' => '', 'Title' => 'Akce'),
    );
    $Order = GetOrderTableHeader($TableColumns, 'Name', 0);
    $Output .= $Order['Output'];
  
    foreach($this->System->ModuleManager->Modules as $Module)
    {
      if(($Module->Dependencies) > 0) $Dependencies = implode(',', $Module->Dependencies);
       else $Dependencies = '&nbsp;';
      $Actions = '';
      if($Module->Installed == true) 
      {
        $Actions .= ' <a href="?action=modules&amp;op=uninstall&amp;name='.$Module->Name.'">Odinstalovat</a>';
        if($Module->Enabled == true) $Actions .= ' <a href="?action=modules&amp;op=disable&amp;name='.$Module->Name.'">Zakázat</a>';
        else $Actions .= ' <a href="?action=modules&amp;op=enable&amp;name='.$Module->Name.'">Povolit</a>';
        if($Module->InstalledVersion != $Module->Version) $Actions .= ' <a href="?action=modules&amp;op=upgrade&amp;name='.$Module->Name.'">Povýšit</a>';
      } else $Actions .= ' <a href="?action=modules&amp;op=install&amp;name='.$Module->Name.'">Instalovat</a>';
   
      $Output .= '<tr><td>'.$Module->Name.'</td>'.
          '<td>'.$Module->Creator.'</td>'.
          '<td>'.$Module->Version.'</td>'.
          '<td>'.$Module->License.'</td>'.
          '<td>'.$YesNo[$Module->Installed].'</td>'.
          '<td>'.$YesNo[$Module->Enabled].'</td>'.
          '<td>'.$Module->Description.'</td>'.
          '<td>'.$Dependencies.'</td>'.
          '<td>'.$Actions.'</td></tr>';
    }
    $Output .= '</table>';
    $Output .= $PageList['Output'];
    //$Output .= '<p><a href="?A=SaveToDb">Uložit do databáze</a></p>';
    return($Output);
  }
  
  function PrepareConfig($Config)
  {
    $Output = '';
    if(!file_exists($this->ConfigDir.'/config.php') and !is_writable($this->ConfigDir))
      $Output .= 'Varování: Konfigurační soubor nebude možné zapsat, protože složka není povolená pro zápis!';
    if(file_exists($this->ConfigDir.'/config.php') and !is_writable($this->ConfigDir.'/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="?action=configure_save" 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'] == 'PasswordEncoded') $Output .= '<input type="password" name="'.$Def['Name'].'"/>';
        if($Def['Type'] == 'Integer') $Output .= '<input type="text" name="'.$Def['Name'].'" value="'.$Value.'"/>';
        if($Def['Type'] == 'Float') $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'] == 'PasswordEncoded') if(array_key_exists($Def['Name'], $_POST) and ($_POST[$Def['Name']] != ''))
        $Value = sha1($_POST[$Def['Name']]);
      if($Def['Type'] == 'Integer') if(array_key_exists($Def['Name'], $_POST))
        $Value = $_POST[$Def['Name']];
      if($Def['Type'] == 'Float') 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($this->ConfigDir.'/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);
  }
}

class PageSetupRedirect extends Page
{
	function Show()
	{
	  $Output = '';
	  if(!$this->Database->Connected()) $Output .= 'Nelze se připojit k databázi.<br>';
	  else {
	    if(!$this->System->Setup->UpdateManager->IsInstalled()) 
	      $Output .= 'Systém vyžaduje instalaci databáze.<br>';
	    else
	    if(!$this->System->Setup->UpdateManager->IsUpToDate()) 
	      $Output .= 'Systém vyžaduje aktualizaci databáze.<br>';
	  }
	  $Output .= 'Pokračujte <a href="'.$this->System->Link('/setup/').'">zde</a>';
		return($Output);
	}
}

class Setup extends Model
{
  var $UpdateManager;
  
  function Start()
  {
    global $DatabaseRevision;
    
    $this->System->RegisterPage('', 'PageSetupRedirect');
    $this->System->RegisterPage('setup', 'PageSetup');

    // Check database persistence structure
    $this->UpdateManager = new UpdateManager();
    $this->UpdateManager->Database = $this->Database;
    $this->UpdateManager->Revision = $DatabaseRevision;
    $Updates = new Updates();
    $this->UpdateManager->Trace = $Updates->Get();
    $this->UpdateManager->InstallMethod = 'FullInstall';
  }  
  
  function Stop()
  {
    unset($this->UpdateManager);
    $this->System->UnregisterPage('');
    $this->System->UnregisterPage('setup');
  }
  
  function CheckState()
  {
    return($this->Database->Connected() and $this->UpdateManager->IsInstalled() and
      $this->UpdateManager->IsUpToDate());
  }
  
  function Install()
  {
  	global $DatabaseRevision;
  	
    $this->Database->query('CREATE TABLE IF NOT EXISTS `SystemVersion` (
  `Id` int(11) NOT NULL AUTO_INCREMENT,
  `Revision` int(11) NOT NULL,
  PRIMARY KEY (`Id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;');
    $this->Database->query("INSERT INTO `SystemVersion` (`Id`, `Revision`) VALUES
      (1, '.$DatabaseRevision.');");
    $this->Database->query("CREATE TABLE IF NOT EXISTS `Module` (
  `Id` int(11) NOT NULL AUTO_INCREMENT,
  `Name` varchar(255) NOT NULL,
  `Title` varchar(255) NOT NULL,
  PRIMARY KEY (`Id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;");
  }
  
  function Uninstall()
  {
    $this->System->ModuleManager->UninstallAll();
    $this->Database->query('DROP TABLE `Module`');
    $this->Database->query('DROP TABLE `SystemVersion`');
  }
  
  function IsInstalled()
  {
    $DbResult = $this->Database->query('SHOW TABLES LIKE "'.$this->VersionTable.'"');
    return($DbResult->num_rows > 0);
  }
  
  function Upgrade()
  {
    $Output = $this->UpdateManager->Upgrade();
    return($Output);
  }
}
