<?php
/**
 * @package linea21\externals\Installer
 * @author $Author$ - Vadim V. Gabriel <vadimg88@gmail.com> - modified by Simon Georget <simon@linea21.com>
 * @link http://www.vadimg.co.il/
 * @version $Id$ 1.0.0a
 * @license GNU Lesser General Public License
 */

/** Load the template class **/
require_once(INSTALLER_PATH . '/Installer_Template.php');


/**
 * Class installer
 *
 */
class Installer
{
	/**
	 * Options property
	 *
	 * @var array
	 */
	protected $_options = array();
	
	/**
	 * View object
	 *
	 * @var object
	 */
	protected $view;
	
	/**
	 * Language array
	 *
	 * @var array
	 */
	protected $lang = array();
	
	protected $default_lang = U_L;
	
	/**
	 * Constructor
	 *
	 */
	public function __construct()
	{
		// get lang from browser
		$lang = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2);
		
		if(file_exists('../languages/' .$lang. '/installer.utf-8.php')) {
			$this->default_lang = $lang;
		} else {
			$this->default_lang = 'fr';
		}
		
		# Do we have a cookie
		if(isset($_COOKIE['lang']) && $_COOKIE['lang'] != '')
		{
			$this->default_lang = $_COOKIE['lang'];
		}
		
		# Change language
		if(isset($_POST['lang']) && $_POST['lang'] != '' && $this->default_lang != $_POST['lang'])
		{
			$path = INSTALLER_PATH . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'lang' . DIRECTORY_SEPARATOR . $_POST['lang'] . '.php';
			
			$path = '../languages/' .$_POST['lang']. '/installer.utf-8.php';
			
			if(file_exists($path))
			{
				$this->default_lang = $_POST['lang'];
				@setcookie('lang', $this->default_lang, time() + 60 * 60 * 24);
				$_POST['lang'] = 0;
				$this->nextStep('index');
			}
		}
		
		# Load the language file
		require_once( '../languages/' .$this->default_lang. '/installer.utf-8.php' );
		
		$this->lang = $lang;
		
		# Load the template class
		$this->view = new Installer_Template($this->lang);
		
		# Are config files writable?
		if(!is_writable('../install/') || !is_writable('../install/installer/data/')) {
			$this->view->error($this->lang['L-13']);
		}
		# Is config folder writable?
		if(!is_writable('../config/')) {
			$this->view->error($this->lang['L-12']);
		}
		
		# Did we run it again?
		if(file_exists(INSTALLER_PATH . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'installer.lock'))
		{
			$this->view->error($this->lang['L-01']);
		}
		
		$allwed_steps = array('index' => 'indexAction', 'db' => 'dbAction', 'cfg' => 'configAction', 'database' => 'dbTables', 'config' => 'configWrite', 'finish' => 'finishInstaller');
		if(!in_array($_POST['step'], array_keys($allwed_steps)))
		{
			$this->nextStep('index');
		}
		
		# Display the right step
		$this->{$allwed_steps[$_POST['step']]}($_POST);
	}
	
	/**
	 * Show welcome message
	 *
	 */
	public function indexAction()
	{
		$_SESSION = array(); // unset session
		
		$options = CultureSelectBox('lang', $this->default_lang);
		
		$this->view->vars = array('options' => $options);
		$this->view->render('index');
	}
	
	/**
	 * Show database setup stuff
	 *
	 */
	public function dbAction()
	{
		$this->view->render('db');
	}
	
	public function configAction()
	{
		$root_path = str_replace('install', '', ROOT_PATH);
		$root_url =str_replace('install/install.php', '', BASE_URL);
		$this->view->vars = array('root_url' => $root_url, 'path' => $root_path);
		$this->view->render('config');
	}
	
	/**
	 * Handle DB table quries
	 *
	 * @param array $options
	 */
	public function dbTables(array $options)
	{
		# Make sure we have an array of options
		if(!is_array($options))
		{
			$this->view->error($this->lang['L-02']);
		}
		# Make sure we have everything we need!
		$required_db_options = array('dbtype', 'dbname', 'dbuser', 'dbpass', 'dbhost');
		foreach ($required_db_options as $required_db_option)
		{
			// set in session
			if(isset($_SESSION[$required_db_option])) unset ($_SESSION[$required_db_option]);
			$_SESSION[$required_db_option] = $options[$required_db_option];
			
			if(!isset($options[$required_db_option]))
			{
				$this->view->error($this->lang['L-03']);
			}
		}
		
		# Pass in to the options property
		$this->_options = $options;
		
		if($this->_options['dbtype']=='mysql') {
			# First test the connection
			$link = mysqli_connect($this->_options['dbhost'], $this->_options['dbuser'], $this->_options['dbpass']);
			if(!$link)
			{
				$this->view->error($this->lang['L-04']);
			}
			
			# Select the DB
			$db_selected = mysqli_select_db($link, $this->_options['dbname']);
			mysqli_query($link, "SET NAMES 'utf8mb4'");
			if(!$db_selected && $this->_options['create_database']==0)
			{
				$this->view->error($this->lang['L-05']);
			}
			elseif (!$db_selected && $this->_options['create_database']==1)
			{
				# Create the DB
				$result = mysqli_query($link, "CREATE DATABASE {$this->_options['dbname']} DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;");
				if (!$result)
				{
					$this->view->error(sprintf($this->lang['L-06'], $this->_options['dbname'], htmlspecialchars(mysqli_error($link))));
				} else {
					$db_selected = mysqli_select_db($link, $this->_options['dbname']);
					// utf8mb4 not supported before 5.5.3 version
					if((int) mysqli_get_server_version($link) < (int) 50503) mysqli_query($link, "SET NAMES 'utf8'");
					else mysqli_query($link, "SET NAMES 'utf8mb4'");
					
				}
			}
		} elseif($this->_options['dbtype']=='pgsql') {
			$link= pg_connect('host=' .$this->_options['dbhost']. ' port=5432 dbname=' . $this->_options['dbname'] . ' user=' . $this->_options['dbuser']. ' password='  . $this->_options['dbpass']);
			if(!$link)
			{
				$this->view->error($this->lang['L-04']);
			}
			
		}
		
		# Load the database stuff
		require_once( '../languages/' .$this->default_lang. '/installer_input.utf-8.php' );
		$path = INSTALLER_PATH . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'database.php' ;
		if(!file_exists($path))
		{
			$this->view->error(sprintf($this->lang['L-07'], $path));
		}
		
		$SQL = array();
		require_once($path);
		
		$count = 0;
		$errors_count = 0;
		
		# Loop if we have any
		if(count($SQL))
		{
			# Start the count
			
			$errors = array();
			foreach ($SQL as $query)
			{
				if($this->_options['dbtype'] == 'mysql')  {
					// since FULLTEXT indexes are not supported in mysql v < 5.6.0 (50600) we replace InnoDB with MyISAM
					if((int) mysqli_get_server_version($link) < (int) 50600) $query = str_ireplace('ENGINE=InnoDB', 'ENGINE=MyISAM', $query);
					// since FULLTEXT indexes are not supported in mysql v < 5.5.3 (50503) we replace utf8mb4 by utf8
					if((int) mysqli_get_server_version($link) < (int) 50503) $query = str_ireplace('utf8mb4', 'utf8', $query);
					$result = mysqli_query($link, $query);
				}
				else $result = pg_query($link, $query);
				
				if (!$result)
				{
					if($this->_options['dbtype'] == 'mysql')  $errors[] = sprintf($this->lang['L-08'], htmlspecialchars(mysqli_error($link)));
					else $errors[] = sprintf($this->lang['L-08'], htmlspecialchars(pg_last_error()));
					$errors_count++;
					continue;
				}
				
				# Increase it
				$count++;
			}
		}
		
		$error_string = '';
		
		# Did we had any errors?
		if(count($errors))
		{
			$error_string = "<br /><br />".sprintf($this->lang['I-14'], implode("<br /><br />", $errors));
		}
		
		# Redirect
		$this->view->vars = array('message' => sprintf($this->lang['L-09'], $count, $errors_count, $error_string), 'button' => $error_string ? $this->lang['I-16'] : $this->lang['I-03']);
		$this->view->render('dbdone');
		
	}
	
	/**
	 * Display everything
	 *
	 */
	public function display()
	{
		$this->view->display();
	}
	
	/**
	 * Write the configuration File
	 *
	 */
	public function configWrite()
	{
		global $l21config;
		
		// update main ini file
		$ini_r=array();
		
		// database settings
		$ini_r['DB_NAME']=$_SESSION['dbname'];
		$ini_r['DB_USER']=$_SESSION['dbuser'];
		$ini_r['DB_PASS']=$_SESSION['dbpass'];
		$ini_r['DB_HOST']=$_SESSION['dbhost'];
		
		$ini_r['LANGUAGE']=$this->default_lang;
		
		if(substr($this->default_lang, 0, 2) == 'en') $ini_r['DATE_FORMAT']="yyyy-mm-dd";
		else $ini_r['DATE_FORMAT']="dd-mm-yyyy";
		
		$ini_r['SITE_NAME']=$_POST['SITE_NAME'];
		$ini_r['SITE_PATH']=$_POST['SITE_PATH'];
		$ini_r['SITE_ROOT_URL']=$_POST['SITE_ROOT_URL'];
		
		// mail settings
		$ini_r['SITE_MAIL']=$_POST['MAIL_FROM'];
		$ini_r['MAIL_FROM']=$_POST['MAIL_FROM'];
		$ini_r['MAIL_FROMNAME']=$_POST['MAIL_FROMNAME'];
		$ini_r['MAIL_REPLY']=$_POST['MAIL_FROM'];
		$ini_r['MAIL_REPLYNAME']=$_POST['MAIL_FROMNAME'];
		$ini_r['SQL']=$_SESSION['dbtype'];
		
		// finally, we cerate a unique SECRET_KEY
		$ini_r['SECRET_KEY'] = md5(uniqid(rand(), true));
		
		$timezone = @ini_get('date.timezone'); // if not test we keep default value
		if(!empty($timezone)) {
			$ini_r['TIME_ZONE'] = $timezone;
		}
		
		$l21config->setParams($ini_r);
		
		$l21config->writeReleaseParams();
		
		$this->finishInstaller();
	}
	
	/**
	 * Finish the installer proccess
	 *
	 */
	public function finishInstaller()
	{
		# Lock the installer
		$path = INSTALLER_PATH . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'installer.lock';
		file_put_contents($path, "installer lock file");
		write_curver(); // we write current version in hidden file (config/.curver)
		$_SESSION = array();
		$this->view->render('finish');
	}
	
	/**
	 * Redirect to the next step
	 *
	 * @param string $step
	 */
	public function nextStep($step)
	{
		$url = BASE_URL . '?step='.$step;
		if(!headers_sent())
		{
			header('Location: '. $url);
			exit;
		}
		
		print "<html><body><meta http-equiv='refresh' content='1;url={$url}'></body></html>";
		exit;
	}
	
	/**
	 * Redirect screen with a message
	 *
	 * @param string $message
	 */
	public function redirectScreen($message, $step)
	{
		$this->view->redirect($message, $step);
	}
	
	
	/**
	 * Destructor
	 *
	 */
	public function __destruct()
	{
		
		
		@mysqli_close();
		if($this->_options['dbtype']=='pgsql') pg_close();

	}
	
}