public function Build($package) { try { $this->Package = $package; $time_start = DUP_Util::GetMicrotime(); $this->Package->SetStatus(DUP_PackageStatus::DBSTART); $this->dbStorePath = "{$this->Package->StorePath}/{$this->File}"; $package_mysqldump = DUP_Settings::Get('package_mysqldump'); $package_phpdump_qrylimit = DUP_Settings::Get('package_phpdump_qrylimit'); $mysqlDumpPath = self::GetMySqlDumpPath(); $mode = $mysqlDumpPath && $package_mysqldump ? 'MYSQLDUMP' : 'PHP'; $reserved_db_filepath = DUPLICATOR_WPROOTPATH . 'database.sql'; $log = "\n********************************************************************************\n"; $log .= "DATABASE:\n"; $log .= "********************************************************************************\n"; $log .= "BUILD MODE: {$mode}"; $log .= $mode == 'PHP' ? "(query limit - {$package_phpdump_qrylimit})\n" : "\n"; $log .= "MYSQLTIMEOUT: " . DUPLICATOR_DB_MAX_TIME . "\n"; $log .= "MYSQLDUMP: "; $log .= $mysqlDumpPath ? "Is Supported" : "Not Supported"; DUP_Log::Info($log); $log = null; //Reserved file found if (file_exists($reserved_db_filepath)) { DUP_Log::Error("Reserverd SQL file detected", "The file database.sql was found at [{$reserved_db_filepath}].\n" . "\tPlease remove/rename this file to continue with the package creation."); } switch ($mode) { case 'MYSQLDUMP': $this->mysqlDump($mysqlDumpPath); break; case 'PHP': $this->phpDump(); break; } DUP_Log::Info("SQL CREATED: {$this->File}"); $time_end = DUP_Util::GetMicrotime(); $time_sum = DUP_Util::ElapsedTime($time_end, $time_start); //File below 10k will be incomplete $sql_file_size = filesize($this->dbStorePath); DUP_Log::Info('file size:' . $sql_file_size); if ($sql_file_size < 10000) { DUP_Log::Error("SQL file size too low.", "File does not look complete. Check permission on file and parent directory at [{$this->dbStorePath}]"); } DUP_Log::Info("SQL FILE SIZE: " . DUP_Util::ByteSize($sql_file_size)); DUP_Log::Info("SQL FILE TIME: " . date("Y-m-d H:i:s")); DUP_Log::Info("SQL RUNTIME: {$time_sum}"); $this->Size = @filesize($this->dbStorePath); $this->Package->SetStatus(DUP_PackageStatus::DBDONE); } catch (Exception $e) { DUP_Log::Error("Runtime error in DUP_Database::Build", "Exception: {$e}"); } }
public function Build($package) { try { $this->Package = $package; $time_start = DUP_Util::GetMicrotime(); $this->Package->SetStatus(DUP_PackageStatus::DBSTART); $package_mysqldump = DUP_Settings::Get('package_mysqldump'); $package_phpdump_qrylimit = DUP_Settings::Get('package_phpdump_qrylimit'); $this->dbStorePath = "{$this->Package->StorePath}/{$this->File}"; $mysqlDumpPath = self::GetMySqlDumpPath(); $mode = $mysqlDumpPath && $package_mysqldump ? 'MYSQLDUMP' : 'PHP'; $mysqlDumpSupport = $mysqlDumpPath ? 'Is Supported' : 'Not Supported'; $log = "\n********************************************************************************\n"; $log .= "DATABASE:\n"; $log .= "********************************************************************************\n"; $log .= "BUILD MODE: {$mode} "; $log .= $mode == 'PHP' ? "(query limit - {$package_phpdump_qrylimit})\n" : "\n"; $log .= "MYSQLDUMP: {$mysqlDumpSupport}\n"; $log .= "MYSQLTIMEOUT: " . DUPLICATOR_DB_MAX_TIME; DUP_Log::Info($log); $log = null; switch ($mode) { case 'MYSQLDUMP': $this->mysqlDump($mysqlDumpPath); break; case 'PHP': $this->phpDump(); break; } DUP_Log::Info("SQL CREATED: {$this->File}"); $time_end = DUP_Util::GetMicrotime(); $time_sum = DUP_Util::ElapsedTime($time_end, $time_start); $sql_file_size = filesize($this->dbStorePath); if ($sql_file_size <= 0) { DUP_Log::Error("SQL file generated zero bytes.", "No data was written to the sql file. Check permission on file and parent directory at [{$this->dbStorePath}]"); } DUP_Log::Info("SQL FILE SIZE: " . DUP_Util::ByteSize($sql_file_size)); DUP_Log::Info("SQL FILE TIME: " . date("Y-m-d H:i:s")); DUP_Log::Info("SQL RUNTIME: {$time_sum}"); $this->Size = @filesize($this->dbStorePath); $this->Package->SetStatus(DUP_PackageStatus::DBDONE); } catch (Exception $e) { DUP_Log::Error("Runtime error in DUP_Database::Build", "Exception: {$e}"); } }
/** * Sets the status to log the state of the build * @param $status The status level for where the package is * @return void */ public function SetStatus($status) { global $wpdb; $packageObj = serialize($this); if (!isset($status)) { DUP_Log::Error("Package SetStatus did not receive a proper code."); } if (!$packageObj) { DUP_Log::Error("Package SetStatus was unable to serialize package object while updating record."); } $wpdb->flush(); $table = $wpdb->prefix . "duplicator_packages"; $sql = "UPDATE `{$table}` SET status = {$status}, package = '{$packageObj}'\tWHERE ID = {$this->ID}"; $wpdb->query($sql); }
/** * CREATE * Creates the zip file and adds the SQL file to the archive */ public static function Create(DUP_Archive $archive) { try { $timerAllStart = DUP_Util::GetMicrotime(); $package_zip_flush = DUP_Settings::Get('package_zip_flush'); self::$compressDir = rtrim(DUP_Util::SafePath($archive->PackDir), '/'); self::$sqlPath = DUP_Util::SafePath("{$archive->Package->StorePath}/{$archive->Package->Database->File}"); self::$zipPath = DUP_Util::SafePath("{$archive->Package->StorePath}/{$archive->File}"); self::$zipArchive = new ZipArchive(); self::$networkFlush = empty($package_zip_flush) ? false : $package_zip_flush; $filterDirs = empty($archive->FilterDirs) ? 'not set' : $archive->FilterDirs; $filterExts = empty($archive->FilterExts) ? 'not set' : $archive->FilterExts; $filterOn = $archive->FilterOn ? 'ON' : 'OFF'; //LOAD SCAN REPORT $json = file_get_contents(DUPLICATOR_SSDIR_PATH_TMP . "/{$archive->Package->NameHash}_scan.json"); self::$scanReport = json_decode($json); DUP_Log::Info("\n********************************************************************************"); DUP_Log::Info("ARCHIVE (ZIP):"); DUP_Log::Info("********************************************************************************"); $isZipOpen = self::$zipArchive->open(self::$zipPath, ZIPARCHIVE::CREATE) === TRUE; if (!$isZipOpen) { DUP_Log::Error("Cannot open zip file with PHP ZipArchive.", "Path location [" . self::$zipPath . "]"); } DUP_Log::Info("ARCHIVE DIR: " . self::$compressDir); DUP_Log::Info("ARCHIVE FILE: " . basename(self::$zipPath)); DUP_Log::Info("FILTERS: *{$filterOn}*"); DUP_Log::Info("DIRS: {$filterDirs}"); DUP_Log::Info("EXTS: {$filterExts}"); DUP_Log::Info("----------------------------------------"); DUP_Log::Info("COMPRESSING"); DUP_Log::Info("SIZE:\t" . self::$scanReport->ARC->Size); DUP_Log::Info("STATS:\tDirs " . self::$scanReport->ARC->DirCount . " | Files " . self::$scanReport->ARC->FileCount); //ADD SQL $isSQLInZip = self::$zipArchive->addFile(self::$sqlPath, "database.sql"); if ($isSQLInZip) { DUP_Log::Info("SQL ADDED: " . basename(self::$sqlPath)); } else { DUP_Log::Error("Unable to add database.sql to archive.", "SQL File Path [" . self::$sqlath . "]"); } self::$zipArchive->close(); self::$zipArchive->open(self::$zipPath, ZipArchive::CREATE); //ZIP DIRECTORIES foreach (self::$scanReport->ARC->Dirs as $dir) { if (self::$zipArchive->addEmptyDir(ltrim(str_replace(self::$compressDir, '', $dir), '/'))) { self::$countDirs++; } else { //Don't warn when dirtory is the root path if (strcmp($dir, rtrim(self::$compressDir, '/')) != 0) { DUP_Log::Info("WARNING: Unable to zip directory: '{$dir}'" . rtrim(self::$compressDir, '/')); } } } /* ZIP FILES: Network Flush * This allows the process to not timeout on fcgi * setups that need a response every X seconds */ if (self::$networkFlush) { foreach (self::$scanReport->ARC->Files as $file) { if (self::$zipArchive->addFile($file, ltrim(str_replace(self::$compressDir, '', $file), '/'))) { self::$limitItems++; self::$countFiles++; } else { DUP_Log::Info("WARNING: Unable to zip file: {$file}"); } //Trigger a flush to the web server after so many files have been loaded. if (self::$limitItems > DUPLICATOR_ZIP_FLUSH_TRIGGER) { $sumItems = self::$countDirs + self::$countFiles; self::$zipArchive->close(); self::$zipArchive->open(self::$zipPath); self::$limitItems = 0; DUP_Util::FcgiFlush(); DUP_Log::Info("Items archived [{$sumItems}] flushing response."); } } //Normal } else { foreach (self::$scanReport->ARC->Files as $file) { if (self::$zipArchive->addFile($file, ltrim(str_replace(self::$compressDir, '', $file), '/'))) { self::$countFiles++; } else { DUP_Log::Info("WARNING: Unable to zip file: {$file}"); } } } DUP_Log::Info(print_r(self::$zipArchive, true)); //-------------------------------- //LOG FINAL RESULTS DUP_Util::FcgiFlush(); $zipCloseResult = self::$zipArchive->close(); $zipCloseResult ? DUP_Log::Info("COMPRESSION RESULT: '{$zipCloseResult}'") : DUP_Log::Error("ZipArchive close failure.", "This hosted server may have a disk quota limit.\nCheck to make sure this archive file can be stored."); $timerAllEnd = DUP_Util::GetMicrotime(); $timerAllSum = DUP_Util::ElapsedTime($timerAllEnd, $timerAllStart); self::$zipFileSize = @filesize(self::$zipPath); DUP_Log::Info("COMPRESSED SIZE: " . DUP_Util::ByteSize(self::$zipFileSize)); DUP_Log::Info("ARCHIVE RUNTIME: {$timerAllSum}"); DUP_Log::Info("MEMORY STACK: " . DUP_Server::GetPHPMemory()); } catch (Exception $e) { DUP_Log::Error("Runtime error in package.archive.zip.php constructor.", "Exception: {$e}"); } }
/** * CREATE * Creates the zip file and adds the SQL file to the archive */ public static function Create(DUP_Archive $archive) { try { $timerAllStart = DUP_Util::GetMicrotime(); $package_zip_flush = DUP_Settings::Get('package_zip_flush'); self::$compressDir = rtrim(DUP_Util::SafePath($archive->PackDir), '/'); self::$filterDirsArray = array_map('DUP_Util::SafePath', explode(";", $archive->FilterDirs, -1)); self::$filterDirsList = $archive->FilterDirs; self::$filterExtsArray = explode(";", $archive->FilterExts, -1); self::$filterExtsList = $archive->FilterExts; self::$filterOn = $archive->FilterOn; self::$sqlPath = DUP_Util::SafePath("{$archive->Package->StorePath}/{$archive->Package->Database->File}"); self::$zipPath = DUP_Util::SafePath("{$archive->Package->StorePath}/{$archive->File}"); self::$zipArchive = new ZipArchive(); self::$filterDirsOn = count(self::$filterDirsArray); self::$filterExtsOn = count(self::$filterExtsArray); self::$networkFlush = empty($package_zip_flush) ? false : $package_zip_flush; DUP_Log::Info("\n********************************************************************************"); DUP_Log::Info("ARCHIVE (ZIP):"); DUP_Log::Info("********************************************************************************"); DUP_Log::Info("ARCHIVE DIR: " . self::$compressDir); DUP_Log::Info("ARCHIVE FILE: " . basename(self::$zipPath)); DUP_Log::Info("FILTER DIRS: " . self::$filterDirsList); DUP_Log::Info("FILTER EXTS: " . self::$filterExtsList); //-------------------------------- //OPEN ZIP $isZipOpen = self::$zipArchive->open(self::$zipPath, ZIPARCHIVE::CREATE) === TRUE; if (!$isZipOpen) { DUP_Log::Error("Cannot open zip file with PHP ZipArchive.", "Path location [" . self::$zipPath . "]"); } //-------------------------------- //ADD FILES DUP_Log::Info("----------------------------------------"); DUP_Log::Info("SCANNING"); $timerFilesStart = DUP_Util::GetMicrotime(); if (self::$filterOn && (self::$filterDirsOn || self::$filterExtsOn)) { DUP_Log::Info("FILTERS *ON*"); !in_array(self::$compressDir, self::$filterDirsArray) ? self::recurseDirsWithFilters(self::$compressDir) : DUP_Log::Info("-filter@[" . self::$compressDir . "]"); } else { DUP_Log::Info("FILTERS *OFF*"); self::recurseDirs(self::$compressDir); } $timerFilesEnd = DUP_Util::GetMicrotime(); $timerFilesSum = DUP_Util::ElapsedTime($timerFilesEnd, $timerFilesStart); DUP_Log::Info("STATS:\tDirs " . self::$countDirs . " | Files " . self::$countFiles . " | Links " . self::$countLinks); DUP_Log::Info("SIZE:\t" . DUP_Util::ByteSize(self::$size)); DUP_Log::Info("TIME:\t{$timerFilesSum}"); DUP_Log::Info("----------------------------------------"); DUP_Log::Info("COMPRESSING"); //-------------------------------- //ADD SQL $isSQLInZip = self::$zipArchive->addFile(self::$sqlPath, "database.sql"); if ($isSQLInZip) { DUP_Log::Info("SQL ADDED: " . basename(self::$sqlPath)); } else { DUP_Log::Error("Unable to add database.sql file to archive.", "SQL File Path [" . self::$sqlath . "]"); } self::$zipArchive->close(); self::$zipArchive->open(self::$zipPath, ZipArchive::CREATE); DUP_Log::Info(print_r(self::$zipArchive, true)); //-------------------------------- //LOG FINAL RESULTS DUP_Util::FcgiFlush(); $zipCloseResult = self::$zipArchive->close(); $zipCloseResult ? DUP_Log::Info("COMPRESSION RESULT: '{$zipCloseResult}'") : DUP_Log::Error("ZipArchive close failure.", "This hosted server may have a disk quota limit.\nCheck to make sure this archive file can be stored."); $timerAllEnd = DUP_Util::GetMicrotime(); $timerAllSum = DUP_Util::ElapsedTime($timerAllEnd, $timerAllStart); self::$zipFileSize = @filesize(self::$zipPath); DUP_Log::Info("COMPRESSED SIZE: " . DUP_Util::ByteSize(self::$zipFileSize)); DUP_Log::Info("ARCHIVE RUNTIME: {$timerAllSum}"); } catch (Exception $e) { DUP_Log::Error("Runtime error in package.archive.zip.php constructor.", "Exception: {$e}"); } }
/** * 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_dbport" => $this->Package->Installer->OptsDBPort, "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}]"); }