ok("$label");
else $this->err("Fail: $label");
}
/**
*
*/
public function execute() {
if(self::TEST_MODE) {
error_reporting(E_ALL | E_STRICT);
ini_set('display_errors', 1);
}
$this->renderHead();
if(isset($_POST['step'])) switch($_POST['step']) {
case 0: $this->compatibilityCheck(); break;
case 1: $this->scanDir(); break;
case 2: $this->extractPackage(); break;
case 3: $this->makeDatabase(); break;
case 4: $this->dbSaveConfig(); break;
//case 5: $this->AdjustConfigPhp(); break;
default:
$this->welcome();
break;
} else $this->welcome();
$this->renderFooter();
}
/**
* Welcome/Intro screen
*
*/
protected function welcome() {
$this->h("Welcome. This tool will guide you through the cloning process.");
$this->p("Thanks for choosing Duplicator as your backup utility! We recommend you to make a backup of any existing file and database before proceeding. This process will overwrite files and create/replace the database. If you need help or have questions during the cloning operation, please stop by our support thread and we'll be glad to help.");
$this->btn("Get Started", 0, 'sign-in');
}
/**
*
*/
protected function renderHead() {
if(!defined("DUPLICATOR_INSTALLER")) die("error.");
$title = "Duplicator installer";
$formAction = "./installer.php";
if(!isset($bgTitle)) $bgTitle = "Installer";
if($title && $formAction) {}
echo "
";
return true;
}
/**
* @param $path
* @param bool $showNote
* @return bool
*/
protected function mkdir($path, $showNote = true) {
if(self::TEST_MODE) return true;
if(is_dir($path) || mkdir($path)) {
chmod($path, octdec($this->chmodDir));
if($showNote) $this->ok("Created directory: $path");
return true;
} else {
if($showNote) $this->err("Error creating directory: $path");
return false;
}
}
/**
* Step 1b: Check for ProcessWire compatibility
*
*/
public function compatibilityCheck()
{
$this->h("Step #1 - Compatibility Check");
if (version_compare(PHP_VERSION, self::MIN_REQUIRED_PHP_VERSION) >= 0) {
$this->ok("PHP version " . PHP_VERSION);
} else {
$this->err("ProcessWire requires PHP version " . self::MIN_REQUIRED_PHP_VERSION . " or newer. You are running PHP " . PHP_VERSION);
}
if (extension_loaded('pdo_mysql')) {
$this->ok("PDO (mysql) database");
} else {
$this->err("PDO (pdo_mysql) is required (for MySQL database)");
}
if (self::TEST_MODE) {
$this->err("Example error message for test mode");
$this->warn("Example warning message for test mode");
}
$this->checkFunction("filter_var", "Filter functions (filter_var)");
$this->checkFunction("mysqli_connect", "MySQLi (not required by core, but may be required by some 3rd party modules)");
$this->checkFunction("imagecreatetruecolor", "GD 2.0 or newer");
$this->checkFunction("json_encode", "JSON support");
$this->checkFunction("preg_match", "PCRE support");
$this->checkFunction("ctype_digit", "CTYPE support");
$this->checkFunction("iconv", "ICONV support");
$this->checkFunction("session_save_path", "SESSION support");
$this->checkFunction("hash", "HASH support");
$this->checkFunction("spl_autoload_register", "SPL support");
if (function_exists('apache_get_modules')) {
if (in_array('mod_rewrite', apache_get_modules())) $this->ok("Found Apache module: mod_rewrite");
else {
$this->err("Apache mod_rewrite does not appear to be installed and is required by ProcessWire.");
}
} else {
// apache_get_modules doesn't work on a cgi installation.
// check for environment var set in htaccess file, as submitted by jmarjie.
$mod_rewrite = getenv('HTTP_MOD_REWRITE') == 'On' || getenv('REDIRECT_HTTP_MOD_REWRITE') == 'On' ? true : false;
if ($mod_rewrite) {
$this->ok("Found Apache module (cgi): mod_rewrite");
} else {
$this->err("Unable to determine if Apache mod_rewrite (required by ProcessWire) is installed. On some servers, we may not be able to detect it until your .htaccess file is place. Please click the 'check again' button at the bottom of this screen, if you haven't already.");
$this->makeTempHtaccess();
}
}
if (class_exists('\ZipArchive')) {
$this->ok("ZipArchive support");
} else {
$this->warn("ZipArchive support was not found. This is required by Duplicator to complete installation.");
}
if ($this->numErrors) {
$this->info("One or more errors were found above. We recommend you correct these issues before proceeding or contact ProcessWire support if you have questions or think the error is incorrect. But if you want to proceed anyway, click Continue below.");
$this->btn("Check Again", 0, 'refresh', false, true);
$this->btn("Continue to Next Step", 1, 'angle-right', true);
} else {
$this->btn("Continue to Next Step", 1, 'angle-right', false);
}
}
protected function makeTempHtaccess() {
$txt = "\n
RewriteEngine On\n
AddDefaultCharset UTF-8\n
\n
SetEnv HTTP_MOD_REWRITE On\n
\n
";
file_put_contents('.htaccess', $txt);
}
/**
* @return bool
*/
protected function scanDir()
{
$ext = self::DUP_PACKAGE_EXTENSION;
$package = false;
$warn = false;
$nfiles = 0;
$this->h('Step #2 - Checking Packages');
$strictArray = array(
'.htaccess',
'index.php',
'wire',
'site'
);
// remove previously generated .htaccess
if(file_exists('.htaccess'))
unlink('.htaccess');
if ($handle = opendir('.')) {
while (false !== ($entry = readdir($handle))) {
if ($entry !== "." && $entry !== "..") {
if(in_array($entry, $strictArray)) {
$warn = true;
$this->warn("ProcessWire structure file detected.");
continue;
}
elseif (strrpos($entry, $ext) !== false) {
$pi = pathinfo($entry);
if($pi['extension'] === 'zip') $package = $entry;
}
$nfiles++;
}
}
closedir($handle);
}
if($nfiles > 2) {
$warn = true;
$this->warn("Other files than the installer and the package files were found.");
$this->info("It is recommended to place the installer and package files into an empty directory.");
}
if(!$package) {
$this->err("Package Not Found.");
$this->btn("Check Again", 1, 'refresh', false, true);
return false;
}
else {
$this->package = $package;
$_SESSION['package'] = $package;
$this->ok("Package Found.");
$warnstr = "Duplicator will extract the package \"$package\".";
$warnstr .= $warn == false ? '.' : ', but we recommend you correct these issues before proceeding.';
$this->info($warnstr);
echo '
';
if($warn) $this->btn("Check Again", 1, 'refresh', false, true);
$this->btn('Continue to Next Step', 2);
echo '
';
$this->p("Note: After you click the button above, be patient … it may take minutes.");
return true;
}
}
/**
* @return bool
*/
protected function extractPackage() {
$this->h("Step #3 - Package Extraction");
$this->package = $_SESSION['package'];
if(is_null($this->package)) {
$this->err("Something went wrong into the installer.");
return false;
}
$path = pathinfo(realpath($this->package), PATHINFO_DIRNAME);
$this->rootPath = $path;
$_SESSION['rootpath'] = $path;
$path .= '/' . self::DUP_TEMP_FOLDER;
if(!is_dir($path)) {
$this->mkdir(self::DUP_TEMP_FOLDER);
}
$zip = new ZipArchive();
$res = $zip->open($this->package);
if ($res == true) {
//$this->action("Extracting \"{$this->package}\" into \"{$path}\"...");
if(is_writable($path))
$zip->extractTo($path);
else {
$zip->close();
$this->err("The temp folder $path is not writable. Please adjust the permissions and try again.");
$this->btn("Check Again", 2, 'refresh', false, true);
return false;
}
if($zip) $zip->close();
$this->ok("The package has been extracted.");
} else {
$this->err("An error occured! Duplicator couldn't open {$this->package}.");
}
$tempfolder = $this->rootPath . DIRECTORY_SEPARATOR . self::DUP_TEMP_FOLDER;
if ($handle = opendir($tempfolder)) {
while (false !== ($entry = readdir($handle))) {
if (strrpos($entry, self::DUP_PW_EXTENSION) !== false) {
$pi = pathinfo($entry);
if($pi['extension'] === 'zip') $pwzip = $entry;
}
if (strrpos($entry, self::DUP_SQL_EXTENSION) !== false) {
$pi = pathinfo($entry);
if($pi['extension'] === 'zip') $sqlzip = $entry;
}
}
}
if(!isset($pwzip) || !$pwzip) {
$this->err("The file containing the ProcessWire structure couldn't be found.");
$this->btn("Check Again", 2, 'refresh', false, true);
return false;
}
else {
$res = $zip->open($path . DIRECTORY_SEPARATOR . $pwzip);
if ($res == true) {
//$this->action("Extracting \"{$pwzip}\" into \"{$this->rootPath}\"...");
$zip->extractTo($this->rootPath);
$zip->close();
$this->ok("The ProcessWire structure has been extracted.");
//$this->btn('Continue to Next Step', 3);
//return true;
}
else {
$this->err("An error occured! Duplicator couldn't open {$pwzip}.");
$this->btn("Check Again", 2, 'refresh', false, true);
return false;
}
}
if(!isset($sqlzip) || !$sqlzip) {
$this->err("The file containing the MySQL database couldn't be found.");
$this->btn("Check Again", 2, 'refresh', false, true);
return false;
}
else {
$res = $zip->open($path . DIRECTORY_SEPARATOR . $sqlzip);
if ($res == true) {
//$this->action("Extracting \"{$sqlzip}\" into \"{$tempfolder}\"...");
$zip->extractTo($tempfolder);
$zip->close();
$files = scandir($tempfolder);
foreach ($files as $file) {
if (strrpos($file, 'sql') !== false) {
$pi = pathinfo($file);
if($pi['extension'] === 'sql') $sqlfile = $file;
}
}
$_SESSION['sqlfile'] = $path . DIRECTORY_SEPARATOR . $sqlfile;
$this->ok("The MySQL database has been extracted.");
$this->btn('Continue to Next Step', 3);
return true;
}
else {
$this->err("An error occured! Duplicator couldn't open {$sqlzip}.");
$this->btn("Check Again", 2, 'refresh', false, true);
return false;
}
}
}
/**
* Step 2: Configure the database and file permission settings
*
* @param array $values
*
*/
protected function makeDatabase() {
$this->h("Step #4 - Database Setup");
$this->p("Please specify a MySQL database and user account on your server. If the database does not exist, we will attempt to create it. If the database already exists, we will overwrite it, the user account should have full read, write and delete permissions on the database.*");
$this->p("*Recommended permissions are select, insert, update, delete, create, alter, index, drop, create temporary tables, and lock tables.", "detail");
if(!is_file($_SESSION['sqlfile'])) {
$this->err("There is no MySQL database file. Please place one there before continuing.");
return false;
}
if(!isset($values['dbName'])) $values['dbName'] = '';
// @todo: are there PDO equivalents for the ini_get()s below?
if(!isset($values['dbHost'])) $values['dbHost'] = ini_get("mysqli.default_host");
if(!isset($values['dbPort'])) $values['dbPort'] = ini_get("mysqli.default_port");
if(!isset($values['dbUser'])) $values['dbUser'] = ini_get("mysqli.default_user");
if(!isset($values['dbPass'])) $values['dbPass'] = ini_get("mysqli.default_pw");
if(!isset($values['dbEngine'])) $values['dbEngine'] = 'MyISAM';
if(!$values['dbHost']) $values['dbHost'] = 'localhost';
if(!$values['dbPort']) $values['dbPort'] = 3306;
if(!isset($values['dbCharset']) || empty($values['dbCharset'])) $values['dbCharset'] = 'utf8';
foreach($values as $key => $value) {
if(strpos($key, 'chmod') === 0) {
$values[$key] = (int) $value;
} else if($key != 'httpHosts') {
$values[$key] = htmlspecialchars($value, ENT_QUOTES, 'utf-8');
}
}
$this->input('dbName', 'DB Name', $values['dbName']);
$this->input('dbUser', 'DB User', $values['dbUser']);
$this->input('dbPass', 'DB Pass', $values['dbPass'], false, 'password', false);
$this->input('dbHost', 'DB Host', $values['dbHost']);
$this->input('dbPort', 'DB Port', $values['dbPort'], true);
echo "