* finish task #5082.

This commit is contained in:
wangyidong
2018-11-09 13:11:46 +08:00
parent 6d3514387c
commit da7534e589
7 changed files with 230 additions and 45 deletions
+21 -4
View File
@@ -91,7 +91,10 @@ class zdb
/* Create sql code. */
$backupSql = "DROP " . strtoupper($tableType) . " IF EXISTS `$table`;\n";
$backupSql .= $this->getSchemaSQL($table, $tableType);
$schemaSQL = $this->getSchemaSQL($table, $tableType);
if($schemaSQL->result) $backupSql .= $schemaSQL->sql;
fwrite($fp, $backupSql);
if($tableType != 'table') continue;
@@ -198,8 +201,22 @@ class zdb
*/
public function getSchemaSQL($table, $type = 'table')
{
$sql = "SHOW CREATE $type `$table`";
$createSql = $this->dbh->query($sql)->fetch(PDO::FETCH_ASSOC);
return $createSql['Create ' . ucfirst($type)] . ";\n";
$return = new stdclass();
$return->result = true;
$return->error = '';
try
{
$sql = "SHOW CREATE $type `$table`";
$createSql = $this->dbh->query($sql)->fetch(PDO::FETCH_ASSOC);
$return->sql = $createSql['Create ' . ucfirst($type)] . ";\n";
return $return;
}
catch(PDOException $e)
{
$return->result = false;
$return->error = $e->getMessage();
return $return;
}
}
}
+144 -22
View File
@@ -21,7 +21,7 @@ class backup extends control
{
parent::__construct($moduleName, $methodName);
$this->backupPath = $this->app->getTmpRoot() . 'backup/';
$this->backupPath = empty($this->config->backup->settingDir) ? $this->app->getTmpRoot() . 'backup/' : $this->config->backup->settingDir;
if(!is_dir($this->backupPath))
{
if(!mkdir($this->backupPath, 0777, true)) $this->view->error = sprintf($this->lang->backup->error->noWritable, dirname($this->backupPath));
@@ -43,14 +43,15 @@ class backup extends control
$backups = array();
if(empty($this->view->error))
{
$sqlFiles = glob("{$this->backupPath}*.sql.php");
$sqlFiles = glob("{$this->backupPath}*.sql*");
if(!empty($sqlFiles))
{
foreach($sqlFiles as $file)
{
$fileName = basename($file);
$backupFile = new stdclass();
$backupFile->time = filemtime($file);
$backupFile->name = str_replace('.sql.php', '', basename($file));
$backupFile->name = substr($fileName, 0, strpos($fileName, '.'));
$backupFile->files[$file] = abs(filesize($file));
if(file_exists($this->backupPath . $backupFile->name . '.file.zip.php'))
{
@@ -60,6 +61,14 @@ class backup extends control
{
$backupFile->files[$this->backupPath . $backupFile->name . '.code.zip.php'] = abs(filesize($this->backupPath . $backupFile->name . '.code.zip.php'));
}
if(file_exists($this->backupPath . $backupFile->name . '.file.zip'))
{
$backupFile->files[$this->backupPath . $backupFile->name . '.file.zip'] = abs(filesize($this->backupPath . $backupFile->name . '.file.zip'));
}
if(file_exists($this->backupPath . $backupFile->name . '.code.zip'))
{
$backupFile->files[$this->backupPath . $backupFile->name . '.code.zip'] = abs(filesize($this->backupPath . $backupFile->name . '.code.zip'));
}
if(file_exists($this->backupPath . $backupFile->name . '.file'))
{
$backupFile->files[$this->backupPath . $backupFile->name . '.file'] = $this->backup->getDirSize($this->backupPath . $backupFile->name . '.file');
@@ -89,9 +98,16 @@ class backup extends control
*/
public function backup($reload = 'no')
{
if($reload == 'yes') session_write_close();
set_time_limit(7200);
$nozip = strpos($this->config->backup->setting, 'nozip') !== false;
$nofile = strpos($this->config->backup->setting, 'nofile') !== false;
$nosafe = strpos($this->config->backup->setting, 'nosafe') !== false;
$fileName = date('YmdHis') . mt_rand(0, 9);
$result = $this->backup->backSQL($this->backupPath . $fileName . '.sql.php');
$backFileName = $this->backupPath . $fileName . '.sql';
if(!$nosafe) $backFileName .= '.php';
$result = $this->backup->backSQL($backFileName);
if(!$result->result)
{
if($reload == 'yes')
@@ -104,14 +120,14 @@ class backup extends control
printf($this->lang->backup->error->noWritable, $this->backupPath);
}
}
$this->backup->addFileHeader($this->backupPath . $fileName . '.sql.php');
if(!$nosafe) $this->backup->addFileHeader($backFileName);
if((extension_loaded('zlib') or strpos($this->config->backup->setting, 'nozip') !== false) and strpos($this->config->backup->setting, 'nofile') === false)
if((extension_loaded('zlib') or $nozip) and !$nofile)
{
$nozip = strpos($this->config->backup->setting, 'nozip') !== false;
$backFileName = $this->backupPath . $fileName . '.file';
if(!$nozip) $backFileName .= '.zip.php';
if(!$nozip) $backFileName .= '.zip';
if(!$nosafe) $backFileName .= '.php';
$result = $this->backup->backFile($backFileName);
if(!$result->result)
@@ -126,10 +142,12 @@ class backup extends control
printf($this->lang->backup->error->backupFile, $result->error);
}
}
if(!$nozip) $this->backup->addFileHeader($backFileName);
if(!$nozip and !$nosafe) $this->backup->addFileHeader($backFileName);
$backFileName = $this->backupPath . $fileName . '.code';
if(!$nozip) $backFileName .= '.zip.php';
if(!$nozip) $backFileName .= '.zip';
if(!$nosafe) $backFileName .= '.php';
$result = $this->backup->backCode($backFileName);
if(!$result->result)
{
@@ -143,7 +161,7 @@ class backup extends control
printf($this->lang->backup->error->backupCode, $result->error);
}
}
if(!$nozip) $this->backup->addFileHeader($backFileName);
if(!$nozip and !$nosafe) $this->backup->addFileHeader($backFileName);
}
/* Delete expired backup. */
@@ -183,10 +201,18 @@ class backup extends control
set_time_limit(7200);
/* Restore database. */
$this->backup->removeFileHeader($this->backupPath . $fileName . '.sql.php');
$result = $this->backup->restoreSQL($this->backupPath . $fileName . '.sql.php');
$this->backup->addFileHeader($this->backupPath . $fileName . '.sql.php');
if(!$result->result) $this->send(array('result' => 'fail', 'message' => sprintf($this->lang->backup->error->restoreSQL, $result->error)));
if(file_exists($this->backupPath . $fileName . '.sql.php'))
{
$this->backup->removeFileHeader($this->backupPath . $fileName . '.sql.php');
$result = $this->backup->restoreSQL($this->backupPath . $fileName . '.sql.php');
$this->backup->addFileHeader($this->backupPath . $fileName . '.sql.php');
if(!$result->result) $this->send(array('result' => 'fail', 'message' => sprintf($this->lang->backup->error->restoreSQL, $result->error)));
}
if(file_exists($this->backupPath . $fileName . '.sql'))
{
$result = $this->backup->restoreSQL($this->backupPath . $fileName . '.sql');
if(!$result->result) $this->send(array('result' => 'fail', 'message' => sprintf($this->lang->backup->error->restoreSQL, $result->error)));
}
/* Restore attatchments. */
if(file_exists($this->backupPath . $fileName . '.file.zip.php'))
@@ -197,6 +223,12 @@ class backup extends control
if(!$result->result) $this->send(array('result' => 'fail', 'message' => sprintf($this->lang->backup->error->resotreFile, $result->error)));
}
if(file_exists($this->backupPath . $fileName . '.file.zip'))
{
$result = $this->backup->restoreFile($this->backupPath . $fileName . '.file.zip');
if(!$result->result) $this->send(array('result' => 'fail', 'message' => sprintf($this->lang->backup->error->resotreFile, $result->error)));
}
if(file_exists($this->backupPath . $fileName . '.file'))
{
$result = $this->backup->restoreFile($this->backupPath . $fileName . '.file');
@@ -206,6 +238,34 @@ class backup extends control
$this->send(array('result' => 'success', 'message' => $this->lang->backup->success->restore));
}
/**
* remove PHP header.
*
* @param string $fileName
* @access public
* @return void
*/
public function rmPHPHeader($fileName)
{
if(file_exists($this->backupPath . $fileName . '.sql.php'))
{
$this->backup->removeFileHeader($this->backupPath . $fileName . '.sql.php');
rename($this->backupPath . $fileName . '.sql.php', $this->backupPath . $fileName . '.sql');
}
if(file_exists($this->backupPath . $fileName . '.file.zip.php'))
{
$this->backup->removeFileHeader($this->backupPath . $fileName . '.file.zip.php');
rename($this->backupPath . $fileName . '.file.zip.php', $this->backupPath . $fileName . '.file.zip');
}
if(file_exists($this->backupPath . $fileName . '.code.zip.php'))
{
$this->backup->removeFileHeader($this->backupPath . $fileName . '.code.zip.php');
rename($this->backupPath . $fileName . '.code.zip.php', $this->backupPath . $fileName . '.code.zip');
}
die(js::reload('parent'));
}
/**
* Delete
*
@@ -223,27 +283,35 @@ class backup extends control
{
die(js::alert(sprintf($this->lang->backup->error->noDelete, $this->backupPath . $fileName . '.sql.php')));
}
if(file_exists($this->backupPath . $fileName . '.sql') and !unlink($this->backupPath . $fileName . '.sql'))
{
die(js::alert(sprintf($this->lang->backup->error->noDelete, $this->backupPath . $fileName . '.sql')));
}
/* Delete attatchments file. */
if(file_exists($this->backupPath . $fileName . '.file.zip.php') and !unlink($this->backupPath . $fileName . '.file.zip.php'))
{
die(js::alert(sprintf($this->lang->backup->error->noDelete, $this->backupPath . $fileName . '.file.zip.php')));
}
if(file_exists($this->backupPath . $fileName . '.file.zip') and !unlink($this->backupPath . $fileName . '.file.zip'))
{
die(js::alert(sprintf($this->lang->backup->error->noDelete, $this->backupPath . $fileName . '.file.zip')));
}
if(file_exists($this->backupPath . $fileName . '.file'))
{
$zfile = $this->app->loadClass('zfile');
$zfile->removeDir($this->backupPath . $fileName . '.file');
}
/* Delete code file. */
if(file_exists($this->backupPath . $fileName . '.code.zip.php') and !unlink($this->backupPath . $fileName . '.code.zip.php'))
{
die(js::alert(sprintf($this->lang->backup->error->noDelete, $this->backupPath . $fileName . '.code.zip.php')));
}
/* Delete attatchments dir. */
if(file_exists($this->backupPath . $fileName . '.file'))
if(file_exists($this->backupPath . $fileName . '.code.zip') and !unlink($this->backupPath . $fileName . '.code.zip'))
{
$zfile = $this->app->loadClass('zfile');
$zfile->removeDir($this->backupPath . $fileName . '.file');
die(js::alert(sprintf($this->lang->backup->error->noDelete, $this->backupPath . $fileName . '.code.zip')));
}
/* Delete code dir. */
if(file_exists($this->backupPath . $fileName . '.code'))
{
$zfile = $this->app->loadClass('zfile');
@@ -286,8 +354,62 @@ class backup extends control
if(isset($data->setting)) $setting = $data->setting;
$this->loadModel('setting')->setItem('system.backup.setting', $setting);
$settingDir = $data->settingDir;
if($data->settingDir == $this->app->getTmpRoot() . 'backup/') $settingDir = '';
$this->setting->setItem('system.backup.settingDir', $settingDir);
die(js::reload('parent.parent'));
}
$this->display();
}
/**
* Ajax get progress.
*
* @access public
* @return void
*/
public function ajaxGetProgress()
{
session_write_close();
$files = glob($this->backupPath . '/*');
rsort($files);
$fileName = basename($files[0]);
$fileName = substr($fileName, 0, strpos($fileName, '.'));
$sqlFileName = $this->backupPath . $fileName . '.sql';
if(!file_exists($sqlFileName)) $sqlFileName .= '.php';
if(file_exists($sqlFileName))
{
$fileSize = abs(filesize($sqlFileName));
$fileSize = $fileSize / 1024 >= 1024 ? round($fileSize / 1024 / 1024, 2) . 'MB' : round($fileSize / 1024, 2) . 'KB';
$message = sprintf($this->lang->backup->progressSQL, $fileSize);
}
$attatchFileName = $this->backupPath . $fileName . '.file';
if(!file_exists($attatchFileName)) $attatchFileName .= '.zip';
if(!file_exists($attatchFileName)) $attatchFileName .= '.php';
if(file_exists($attatchFileName))
{
$fileSize = abs(filesize($attatchFileName));
if(is_dir($attatchFileName)) $fileSize = $this->backup->getDirSize($attatchFileName);
$fileSize = $fileSize / 1024 >= 1024 ? round($fileSize / 1024 / 1024, 2) . 'MB' : round($fileSize / 1024, 2) . 'KB';
$message = sprintf($this->lang->backup->progressAttatch, $fileSize);
}
$codeFileName = $this->backupPath . $fileName . '.code';
if(!file_exists($codeFileName)) $codeFileName .= '.zip';
if(!file_exists($codeFileName)) $codeFileName .= '.php';
if(file_exists($codeFileName))
{
$fileSize = abs(filesize($codeFileName));
if(is_dir($codeFileName)) $fileSize = $this->backup->getDirSize($codeFileName);
$fileSize = $fileSize / 1024 >= 1024 ? round($fileSize / 1024 / 1024, 2) . 'MB' : round($fileSize / 1024, 2) . 'KB';
$message = sprintf($this->lang->backup->progressCode, $fileSize);
}
die($message);
}
}
+12
View File
@@ -4,6 +4,18 @@ $(function()
{
$('#waitting .modal-body #backupType').html(backup);
$('#waitting').modal('show');
setInterval(function()
{
$.get(createLink('backup', 'ajaxGetProgress'), function(data)
{
$('#waitting .modal-content #message').html(data);
});
}, 1000);
})
$('.rmPHPHeader').click(function()
{
$('#waitting .modal-body #backupType').html(rmPHPHeader);
$('#waitting').modal('show');
})
$('.restore').click(function()
+20 -14
View File
@@ -1,26 +1,32 @@
<?php
$lang->backup->common = '备份';
$lang->backup->index = '备份首页';
$lang->backup->history = '备份历史';
$lang->backup->delete = '删除备份';
$lang->backup->backup = '备份';
$lang->backup->restore = '还原';
$lang->backup->change = '修改保留时间';
$lang->backup->changeAB = '修改';
$lang->backup->common = '备份';
$lang->backup->index = '备份首页';
$lang->backup->history = '备份历史';
$lang->backup->delete = '删除备份';
$lang->backup->backup = '备份';
$lang->backup->restore = '还原';
$lang->backup->change = '修改保留时间';
$lang->backup->changeAB = '修改';
$lang->backup->rmPHPHeader = '去除安全语句';
$lang->backup->time = '备份时间';
$lang->backup->files = '备份文件';
$lang->backup->size = '大小';
$lang->backup->setting = '设置';
$lang->backup->setting = '设置';
$lang->backup->settingDir = '备份目录';
$lang->backup->settingList['nofile'] = '不备份附件和代码';
$lang->backup->settingList['nozip'] = '只拷贝文件';
$lang->backup->settingList['nosafe'] = '不需要防下载设置';
$lang->backup->waitting = '<span id="backupType"></span>正在进行中,请稍候...';
$lang->backup->confirmDelete = '是否删除备份?';
$lang->backup->confirmRestore = '是否还原该备份?';
$lang->backup->holdDays = '备份保留最近 %s 天';
$lang->backup->restoreTip = '还原功能只还原附件和数据库,如果需要还原代码,可以手动还原。';
$lang->backup->waitting = '<span id="backupType"></span>正在进行中,请稍候...';
$lang->backup->progressSQL = '<p>SQL备份中,已备份%s</p>';
$lang->backup->progressAttatch = '<p>SQL备份完成</p><p>附件备份中,已备份%s</p>';
$lang->backup->progressCode = '<p>SQL备份完成</p><p>附件备份完成</p><p>代码备份中,已备份%s</p>';
$lang->backup->confirmDelete = '是否删除备份?';
$lang->backup->confirmRestore = '是否还原该备份?';
$lang->backup->holdDays = '备份保留最近 %s 天';
$lang->backup->restoreTip = '还原功能只还原附件和数据库,如果需要还原代码,可以手动还原。';
$lang->backup->success = new stdclass();
$lang->backup->success->backup = '备份成功!';
+11 -2
View File
@@ -40,14 +40,17 @@ class backupModel extends model
$nozip = strpos($this->config->backup->setting, 'nozip') !== false;
if(!$nozip)
{
$oldDir = getcwd();
chdir($this->app->getTmpRoot());
$this->app->loadClass('pclzip', true);
$zip = new pclzip($backupFile);
$zip->create($this->app->getAppRoot() . 'www/data/', PCLZIP_OPT_REMOVE_PATH, $this->app->getAppRoot() . 'www/data/');
$zip->create($this->app->getAppRoot() . 'www/data/', PCLZIP_OPT_REMOVE_PATH, $this->app->getAppRoot() . 'www/data/', PCLZIP_OPT_TEMP_FILE_ON);
if($zip->errorCode() != 0)
{
$return->result = false;
$return->error = $zip->errorInfo();
}
chdir($oldDir);
}
else
{
@@ -88,14 +91,17 @@ class backupModel extends model
$nozip = strpos($this->config->backup->setting, 'nozip') !== false;
if(!$nozip)
{
$oldDir = getcwd();
chdir($this->app->getTmpRoot());
$this->app->loadClass('pclzip', true);
$zip = new pclzip($backupFile);
$zip->create($fileList, PCLZIP_OPT_REMOVE_PATH, $appRoot);
$zip->create($fileList, PCLZIP_OPT_REMOVE_PATH, $appRoot, PCLZIP_OPT_TEMP_FILE_ON);
if($zip->errorCode() != 0)
{
$return->result = false;
$return->error = $zip->errorInfo();
}
chdir($oldDir);
}
else
{
@@ -150,6 +156,8 @@ class backupModel extends model
$nozip = strpos($this->config->backup->setting, 'nozip') !== false;
if(!$nozip)
{
$oldDir = getcwd();
chdir($this->app->getTmpRoot());
$this->app->loadClass('pclzip', true);
$zip = new pclzip($backupFile);
if($zip->extract(PCLZIP_OPT_PATH, $this->app->getAppRoot() . 'www/data/') == 0)
@@ -157,6 +165,7 @@ class backupModel extends model
$return->result = false;
$return->error = $zip->errorInfo();
}
chdir($oldDir);
}
else
{
+13 -2
View File
@@ -50,8 +50,10 @@
<tbody class='text-center'>
<?php foreach($backups as $backupFile):?>
<?php $rowspan = count($backupFile->files);?>
<?php $i = 0?>
<?php $i = 0;?>
<?php $isPHP = false;?>
<?php foreach($backupFile->files as $file => $size):?>
<?php if(!$isPHP) $isPHP = strpos($file, '.php') !== false;?>
<tr>
<?php if($i == 0):?>
<td <?php if($rowspan > 1) echo "rowspan='$rowspan'"?>><?php echo date(DT_DATETIME1, $backupFile->time);?></td>
@@ -61,6 +63,11 @@
<?php if($i == 0):?>
<td <?php if($rowspan > 1) echo "rowspan='$rowspan'"?>>
<?php
if(common::hasPriv('backup', 'rmPHPHeader') and $isPHP)
{
echo html::a(inlink('rmPHPHeader', "file={$backupFile->name}"), $lang->backup->rmPHPHeader, 'hiddenwin', "class='rmPHPHeader'");
echo "<br />";
}
if(common::hasPriv('backup', 'restore')) echo html::a(inlink('restore', "file={$backupFile->name}&confirm=yes"), $lang->backup->restore, 'hiddenwin', "class='restore'");
if(common::hasPriv('backup', 'delete')) echo html::a(inlink('delete', "file=$backupFile->name"), $lang->delete, 'hiddenwin');
?>
@@ -76,11 +83,15 @@
<div class="modal fade" id="waitting" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog w-300px">
<div class="modal-content">
<div class="modal-body"><?php echo $lang->backup->waitting?></div>
<div class="modal-body">
<p><?php echo $lang->backup->waitting?></p>
<div id='message'><?php echo sprintf($lang->backup->progressSQL, 0);?></div>
</div>
</div>
</div>
</div>
<?php js::set('backup', $lang->backup->backup);?>
<?php js::set('rmPHPHeader', $lang->backup->rmPHPHeader);?>
<?php js::set('confirmRestore', $lang->backup->confirmRestore);?>
<?php js::set('restore', $lang->backup->restore);?>
<?php include '../../common/view/footer.html.php';?>
+9 -1
View File
@@ -18,12 +18,20 @@
<form method='post' target='hiddenwin'>
<table class='w-p100'>
<tr>
<td style='height:50px;vertical-align:top'>
<td style='height:80px;vertical-align:top'>
<div class='input-group'>
<?php echo html::checkbox('setting', $lang->backup->settingList, isset($config->backup->setting) ? $config->backup->setting : '');?>
</div>
</td>
</tr>
<tr>
<td>
<div class='input-group'>
<span class='input-group-addon'><?php echo $lang->backup->settingDir;?></span>
<?php echo html::input('settingDir', !empty($config->backup->settingDir) ? $config->backup->settingDir : $this->app->getTmpRoot() . 'backup/', "class='form-control'");?>
</div>
</td>
</tr>
<tr><td><?php echo html::submitButton('', '', 'btn btn-primary');?></td></tr>
</table>
</form>