<?php

if ( ! defined( 'DUPLICATOR_VERSION' ) ) exit; // Exit if accessed directly

class DUP_Installer {
	
	//PUBLIC
	public $File;
	public $Size = 0;
	public $OptsDBHost;
	public $OptsDBName;
	public $OptsDBUser;
	public $OptsSSLAdmin;
	public $OptsSSLLogin;
	public $OptsCacheWP;
	public $OptsCachePath;
	public $OptsURLNew;
	
	//PROTECTED
	protected $Package;
	
	//CONSTRUCTOR
	function __construct($package) {
		 $this->Package = $package;
	}
	
	public function Build($package) {
		
		$this->Package = $package;
		
		DUP_Log::Info("\n********************************************************************************");
		DUP_Log::Info("MAKE INSTALLER:");
		DUP_Log::Info("********************************************************************************");
		DUP_Log::Info("Build Start");

		$template_uniqid = uniqid('') . '_' . time();
		$template_path	= DUP_Util::SafePath(DUPLICATOR_SSDIR_PATH_TMP  . "/installer.template_{$template_uniqid}.php");
		$main_path		= DUP_Util::SafePath(DUPLICATOR_PLUGIN_PATH . 'installer/build/main.installer.php');
		@chmod($template_path, 0777);
		@chmod($main_path, 0777);

		@touch($template_path);
		$main_data = file_get_contents("{$main_path}");
		$template_result = file_put_contents($template_path, $main_data);
		if ($main_data === false || $template_result == false) {
			$err_info ="These files may have permission issues. Please validate that PHP has read/write access.\n";
			$err_info .= "Main Installer: '{$main_path}' \nTemplate Installer: '$template_path'";
			DUP_Log::Error("Install builder failed to generate files.", "{$err_info}");
		}

		$embeded_files = array(
			"assets/inc.libs.css.php"		=> "@@INC.LIBS.CSS.PHP@@",
			"assets/inc.css.php"			=> "@@INC.CSS.PHP@@",
			"assets/inc.libs.js.php"		=> "@@INC.LIBS.JS.PHP@@",
			"assets/inc.js.php"				=> "@@INC.JS.PHP@@",
			"classes/class.logging.php"		=> "@@CLASS.LOGGING.PHP@@",
			"classes/class.utils.php"		=> "@@CLASS.UTILS.PHP@@",
			"classes/class.config.php"		=> "@@CLASS.CONFIG.PHP@@",
			"classes/class.serializer.php"	=> "@@CLASS.SERIALIZER.PHP@@",
			"ajax.step1.php"				=> "@@AJAX.STEP1.PHP@@",
			"ajax.step2.php"				=> "@@AJAX.STEP2.PHP@@",
			"view.step1.php"				=> "@@VIEW.STEP1.PHP@@",
			"view.step2.php"				=> "@@VIEW.STEP2.PHP@@",
			"view.step3.php"				=> "@@VIEW.STEP3.PHP@@",
			"view.help.php"					=> "@@VIEW.HELP.PHP@@",);

		foreach ($embeded_files as $name => $token) {
			$file_path = DUPLICATOR_PLUGIN_PATH . "installer/build/{$name}";
			@chmod($file_path, 0777);

			$search_data = @file_get_contents($template_path);
			$insert_data = @file_get_contents($file_path);
			file_put_contents($template_path, str_replace("${token}", "{$insert_data}", $search_data));
			if ($search_data === false || $insert_data == false) {
				DUP_Log::Error("Installer generation failed at {$token}.");
			}
			@chmod($file_path, 0644);
		}

		@chmod($template_path, 0644);
		@chmod($main_path, 0644);

		DUP_Log::Info("Build Finished");
		$this->createFromTemplate($template_path);
		$storePath = "{$this->Package->StorePath}/{$this->File}";
		$this->Size = @filesize($storePath);
		$this->addBackup();
		
	}
	
	
	/**
	*  createZipBackup
	*  Puts an installer zip file in the archive for backup purposes.
	*/
	private function addBackup() {
		
		$zipPath   = DUP_Util::SafePath("{$this->Package->StorePath}/{$this->Package->Archive->File}");
		$installer = DUP_Util::SafePath(DUPLICATOR_SSDIR_PATH_TMP) . "/{$this->Package->NameHash}_installer.php";
		
		$zipArchive	= new ZipArchive();
		if ($zipArchive->open($zipPath, ZIPARCHIVE::CREATE) === TRUE) {
			if ($zipArchive->addFile($installer, "installer-backup.php"))  {
				DUP_Log::Info("Added to archive");
			} else {
				DUP_Log::Info("Unable to add installer-backup.php to archive.", "Installer File Path [{$installer}]");
			}
			$zipArchive->close();
		}
	}
	
	/**
	*  createFromTemplate
	*  Generates the final installer file from the template file
	*/
	private function createFromTemplate($template) {
		
		global $wpdb;
		
		DUP_Log::Info("Preping for use");
		$installer = DUP_Util::SafePath(DUPLICATOR_SSDIR_PATH_TMP) . "/{$this->Package->NameHash}_installer.php";
		
		//Option values to delete at install time
		$deleteOpts = $GLOBALS['DUPLICATOR_OPTS_DELETE'];

		$replace_items = Array(
			"fwrite_url_old"			=> get_option('siteurl'),
			"fwrite_package_name"		=> "{$this->Package->NameHash}_archive.zip",
			"fwrite_package_notes"		=> $this->Package->Notes,
			"fwrite_secure_name"		=> $this->Package->NameHash,
			"fwrite_url_new"			=> $this->Package->Installer->OptsURLNew,
			"fwrite_dbhost"				=> $this->Package->Installer->OptsDBHost,
			"fwrite_dbname"				=> $this->Package->Installer->OptsDBName,
			"fwrite_dbuser"				=> $this->Package->Installer->OptsDBUser,
			"fwrite_dbpass"				=> '',
			"fwrite_ssl_admin"			=> $this->Package->Installer->OptsSSLAdmin,
			"fwrite_ssl_login"			=> $this->Package->Installer->OptsSSLLogin,
			"fwrite_cache_wp"			=> $this->Package->Installer->OptsCacheWP,
			"fwrite_cache_path"			=> $this->Package->Installer->OptsCachePath,
			"fwrite_wp_tableprefix"		=> $wpdb->prefix,
			"fwrite_opts_delete"		=> json_encode($deleteOpts),
			"fwrite_blogname"			=> esc_html(get_option('blogname')),
			"fwrite_wproot"				=> DUPLICATOR_WPROOTPATH,
			"fwrite_duplicator_version" => DUPLICATOR_VERSION);

		if (file_exists($template) && is_readable($template)) {
			$err_msg = "ERROR: Unable to read/write installer. \nERROR INFO: Check permission/owner on file and parent folder.\nInstaller File = <{$installer}>";
			$install_str = $this->parseTemplate($template, $replace_items);
			(empty($install_str))
					? DUP_Log::Error("{$err_msg}" , "DUP_Installer::createFromTemplate => file-empty-read")
					: DUP_Log::Info("Template parsed with new data");
			
			//INSTALLER FILE
			$fp = (!file_exists($installer)) ? fopen($installer, 'x+') : fopen($installer, 'w');
			if (! $fp || ! fwrite($fp, $install_str, strlen($install_str))) {
				DUP_Log::Error("{$err_msg}", "DUP_Installer::createFromTemplate => file-write-error");
			}

			@fclose($fp);
		} else {
			DUP_Log::Error("Installer Template missing or unreadable.", "Template [{$template}]");
		}
		@unlink($template);
		DUP_Log::Info("Complete [{$installer}]");
	}
	
	/**
	*  parseTemplate
	*  Tokenize a file based on an array key 
	*
	*  @param string $filename		The filename to tokenize
	*  @param array  $data			The array of key value items to tokenize
	*/
	private function parseTemplate($filename, $data) {
		$q = file_get_contents($filename);
		foreach ($data as $key => $value) {
			//NOTE: Use var_export as it's probably best and most "thorough" way to
			//make sure the values are set correctly in the template.  But in the template,
			//need to make things properly formatted so that when real syntax errors
			//exist they are easy to spot.  So the values will be surrounded by quotes

			$find = array ("'%{$key}%'", "\"%{$key}%\"");
			$q = str_replace($find, var_export($value, true), $q);
			//now, account for places that do not surround with quotes...  these
			//places do NOT need to use var_export as they are not inside strings
			$q = str_replace('%' . $key . '%', $value, $q);
		}
		return $q;
	}
	
}
?>