/** * Import products */ public function actionImport() { $this->pageName = Yii::t('CsvModule.admin', 'IMPORT_PRODUCTS'); $importer = new CsvImporter(); $importer->deleteDownloadedImages = Yii::app()->request->getPost('remove_images'); if (Yii::app()->request->isPostRequest && isset($_FILES['file'])) { $importer->file = $_FILES['file']['tmp_name']; if ($importer->validate() && !$importer->hasErrors()) { // Create db backup if (isset($_POST['create_dump']) && $_POST['create_dump']) { //Yii::import('application.components.DatabaseDumper'); $dumper = new DatabaseDumper(); $file = Yii::getPathOfAlias('webroot.protected.backups') . DIRECTORY_SEPARATOR . 'dump_' . date('Y-m-d_H_i_s') . '.sql'; if (is_writable(Yii::getPathOfAlias('webroot.protected.backups'))) { if (function_exists('gzencode')) { file_put_contents($file . '.gz', gzencode($dumper->getDump())); } else { file_put_contents($file, $dumper->getDump()); } } else { throw new CHttpException(503, Yii::t('CsvModule.admin', 'ERROR_WRITE_BACKUP')); } } $importer->import(); } } $this->render('import', array('importer' => $importer)); }
/** * dumpSQL * * @param SplFileInfo $backupSQLFile * * @return void */ protected function dumpSQL(\SplFileInfo $backupSQLFile) { // Delete old file if (is_file($backupSQLFile->getPathname())) { unlink($backupSQLFile->getPathname()); } try { $sql = DatabaseDumper::dump($this->getOption('database', array())); } catch (RuntimeException $e) { $this->close($e->getMessage()); } file_put_contents($backupSQLFile->getPathname(), $sql); }
/** * @see Action::execute() */ public function execute() { parent::execute(); // export is not finished. export further if (empty($this->downloadFile)) { // get session data $sessionData = WCF::getSession()->getVar('databaseExportData'); $loopTimeLimit = $sessionData['loopTimeLimit']; $isGzip = $sessionData['isGzip']; $limit = $sessionData['limit']; $tableName = $sessionData['tableName']; $offset = $sessionData['offset']; $importErrors = ''; $stepInfo = array(); // start export operations $loopStart = time(); $backupFile = $sessionData['backupFile']; $tables = $sessionData['tables']; // TODO: check if file could be opened (e.g. if directory exists) // open backupfile if ($isGzip) { $file = new ZipFile($backupFile, $offset == -1 ? 'wb' : 'ab'); } else { $file = new File($backupFile, $offset == -1 ? 'wb' : 'ab'); } // export database operations (only up to $limit) $stepInfo = DatabaseDumper::export($file, $tables, $limit, $loopTimeLimit, $loopStart, $offset, $tableName); // delete completed tables from session foreach ($stepInfo['completedTables'] as $table) { $key = array_search($table, $sessionData['tables']); if ($key !== false) { unset($sessionData['tables'][$key]); } } $loopEnd = time(); $duration = $loopEnd - $loopStart; // check if limit should be changed (more or less db-operations per loop) if ($stepInfo['resetLimit']) { $sessionData['limit'] = 250; } elseif ($duration != $loopTimeLimit) { // higher export step size if ($duration > 0) { $sessionData['limit'] = round($limit * ($loopTimeLimit / $duration), 0); } else { $sessionData['limit'] = $limit * 10; } } // refresh session data $sessionData['tableName'] = $stepInfo['tableName']; $sessionData['offset'] = $stepInfo['offset']; $sessionData['remain'] -= $stepInfo['done']; // show finish if ($sessionData['remain'] <= 0) { // cleanup session data. save backupFile to session WCF::getSession()->register('databaseExportData', $backupFile); WCF::getTPL()->assign(array('export' => true, 'success' => true, 'totalTables' => $sessionData['tableCount'], 'totalRecords' => $sessionData['rowCount'], 'backupFile' => $backupFile)); WCF::getTPL()->append('message', WCF::getTPL()->fetch('dbMessage')); $title = 'wcf.acp.db.progress.finish'; $this->calcProgress($sessionData['count'] - $sessionData['remain'], $sessionData['count']); $this->finish($title, 'index.php?form=DatabaseExport&packageID=' . PACKAGE_ID . SID_ARG_2ND_NOT_ENCODED); } WCF::getSession()->register('databaseExportData', $sessionData); // refresh progressbar and go to the next step $title = 'wcf.acp.db.export.progress.working'; $this->calcProgress($sessionData['count'] - $sessionData['remain'], $sessionData['count']); $this->nextLoop($title); } else { $fileName = basename($this->downloadFile); $backupFile = WCF::getSession()->getVar('databaseExportData'); WCF::getSession()->unregister('databaseExportData'); if ($this->downloadFile == $backupFile) { // file type header('Content-Type: application/octet-stream'); // file name header('Content-Disposition: attachment; filename="' . $fileName . '"'); // send file size header('Content-Length: ' . filesize($this->downloadFile)); // no cache headers header('Pragma: no-cache'); header('Expires: 0'); // send file readfile($this->downloadFile); } else { throw new SystemException("Expected parameter for download file: " . $this->downloadFile, 102000); } } }
/** * @see Action::execute() */ public function execute() { parent::execute(); // get session data $sessionData = WCF::getSession()->getVar('databaseImportData'); $filesize = $sessionData['filesize']; $isGzip = $sessionData['isGzip']; $extendedCommand = $sessionData['extendedCommand']; $offset = $sessionData['offset']; $charset = $sessionData['importCharset']; $ignoreErrors = $sessionData['ignoreErrors']; $importErrors = ''; $stepInfo = array(); // start export operations $loopStart = time(); $importFile = $sessionData['importFile']; if ($isGzip) { $file = new ZipFile($importFile, 'rb'); } else { $file = new File($importFile, 'rb'); } // import database operations (only up to $this->limit) $loopInfo = DatabaseDumper::import($file, $filesize, $isGzip, $this->limit, $loopStart, $offset, $charset, $extendedCommand, $ignoreErrors); $file->close(); // store charset if (!empty($loopInfo['charset']) && $loopInfo['charset'] != $sessionData['wcfCharset']) { $sessionData['importCharset'] = $loopInfo['charset']; } // delete aftereffected erros (no insert errors will be displayed if the table caused an error before) $tableErrors = $sessionData['tableErrors']; foreach ($loopInfo['errors']['messages'] as $key => $message) { if (preg_match("/CREATE TABLE `?(\\w+)`?/i", $message, $match)) { $tableErrors[] = $match[1]; } elseif (preg_match("/(INSERT|REPLACE).*?INTO `?(\\w+)`?/i", $message, $match)) { if (in_array($match[1], $tableErrors)) { unset($loopInfo['errors']['messages'][$key]); unset($loopInfo['errors']['errorDescriptions'][$key]); } else { $tableErrors[] = $match[1]; } } } // save errors $errors = array('messages' => array_merge($sessionData['errors']['messages'], $loopInfo['errors']['messages']), 'errorDescriptions' => array_merge($sessionData['errors']['errorDescriptions'], $loopInfo['errors']['errorDescriptions'])); $sessionData['errors'] = $errors; $sessionData['tableErrors'] = $tableErrors; // refresh session data $sessionData['extendedCommand'] = $loopInfo['extendedCommand']; $sessionData['offset'] = $loopInfo['offset']; $sessionData['remain'] -= $loopInfo['done']; $sessionData['commandCount'] += $loopInfo['commandCount']; // calculate progressbar $this->calcProgress($sessionData['count'] - $sessionData['remain'], $sessionData['count']); // show finish if ($sessionData['remain'] <= 0) { // reset charset for database connection if (!empty($sessionData['importCharset'])) { WCF::getDB()->setCharset($sessionData['wcfCharset']); } // cleanup session data WCF::getSession()->unregister('databaseImportData'); // delete imported upload/remote file if ($sessionData['isTmpFile']) { @unlink($importFile); } // clear all standalone caches // get standalone package directories $sql = "SELECT\tpackageDir \n\t\t\t\tFROM\twcf" . WCF_N . "_package\n\t\t\t\tWHERE\tstandalone = 1\n\t\t\t\t\tAND packageDir <> ''"; $result = WCF::getDB()->sendQuery($sql); while ($row = WCF::getDB()->fetchArray($result)) { // check if standalone package got cache directory $realPackageDir = FileUtil::addTrailingSlash(FileUtil::getRealPath(WCF_DIR . $row['packageDir'])); if (file_exists($realPackageDir . 'cache')) { // delete all cache files WCF::getCache()->clear($realPackageDir . 'cache', '*.php', true); } } // clear wcf cache WCF::getCache()->clear(WCF_DIR . 'cache', '*.php', true); // delete all language files LanguageEditor::updateAll(); // set data for template WCF::getTPL()->assign(array('import' => true, 'success' => empty($errors['messages']) && $sessionData['commandCount'] > 0, 'commandCount' => $sessionData['commandCount'], 'errors' => $errors)); WCF::getTPL()->append('message', WCF::getTPL()->fetch('dbMessage')); // show finish template $title = 'wcf.acp.db.progress.finish'; $this->finish($title, 'index.php?form=DatabaseImport&packageID=' . PACKAGE_ID . SID_ARG_2ND_NOT_ENCODED); } WCF::getSession()->register('databaseImportData', $sessionData); // next loop $title = 'wcf.acp.db.import.progress.working'; $this->nextLoop($title); }
/** * @see Form::save() */ public function save() { parent::save(); // build session data array $sessionData = array(); $sessionData['loopTimeLimit'] = $this->loopTimeLimit; $sessionData['isGzip'] = $this->isGzip; $sessionData['tableName'] = ''; $tablecount = 0; $rowCount = 0; $sessionData['offset'] = -1; // get all tables if ($this->exportAll) { $this->readLoggedTables(); $this->exportTables = $this->loggedTables; } // prepare session data $sessionData['limit'] = $this->limit; $sessionData['backupFile'] = FileUtil::getRealPath(WCF_DIR . 'acp/backup/' . $this->backupFileName); $sessionData['tables'] = $this->exportTables; // calculate total steps $tableCount = count($this->exportTables); $tables = DatabaseDumper::getTableStates($this->exportTables); $rowCount = 0; foreach ($tables as $table) { $rowCount += $table['Rows']; } $sessionData['tableCount'] = $tableCount; $sessionData['rowCount'] = $rowCount; $sessionData['count'] = $sessionData['remain'] = $tableCount + $rowCount; WCF::getSession()->register('databaseExportData', $sessionData); $this->saved(); WCF::getTPL()->assign(array('pageTitle' => WCF::getLanguage()->get('wcf.acp.db.export.pageHeadline'), 'url' => 'index.php?action=DatabaseExport&packageID=' . PACKAGE_ID . SID_ARG_2ND_NOT_ENCODED, 'progress' => 0)); WCF::getTPL()->display('worker'); exit; }
public function cronDbBackup() { require_once WCF_DIR . 'lib/system/database/DatabaseDumper.class.php'; $allTables = WCF::getDB()->getTableNames(); $tablesEx = DatabaseDumper::getTableStates($allTables); $rowCount = 0; $tables = array(); foreach ($tablesEx as $table) { $rowCount += $table['Rows']; $tables[] = $table['Name']; } // comment buffer $limit = $rowCount + 10000; $offset = -1; $backupFile = WCF_DIR . 'acp/backup/' . date('YmdHis') . '.sql.gz'; $file = new ZipFile($backupFile, 'wb'); $loopTimeLimit = 3600; $loopStart = time(); $tableName = ''; // write header info $head = "-- WoltLab Community Framework\n"; $head .= "-- database: " . WCF::getDB()->getDatabaseName() . "\n"; $head .= "-- generated at " . date('r') . "\n\n"; $head .= "-- DO NOT EDIT THIS FILE\n\n"; $head .= "-- WCF DATABASE CHARSET\n"; $head .= "SET NAMES " . WCF::getDB()->getCharset() . ";\n\n"; $file->write($head); @set_time_limit(3600); DatabaseDumper::export($file, $tables, $limit, $loopTimeLimit, $loopStart, 0, $tableName); }