Skip to content

Commit 37659b2

Browse files
author
ShingChi
committed
更新备份插件,支持后台导入
1 parent 698da9e commit 37659b2

6 files changed

+766
-0
lines changed

Export/Action.php

+232
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
<?php
2+
3+
class Export_Action extends Typecho_Widget implements Widget_Interface_Do
4+
{
5+
/**
6+
* 导出动作
7+
*
8+
* @access public
9+
* @return void
10+
*/
11+
public function doExport()
12+
{
13+
// 获取POST值
14+
$tableSelect = $this->request->get('tableSelect');
15+
16+
// 获取SQL语句
17+
$content = $this->getSql($tableSelect);
18+
19+
// 获取备份目录并设置文件
20+
$config = Typecho_Widget::widget('Widget_Options')->plugin('Export');
21+
$path = __TYPECHO_ROOT_DIR__ . '/' . trim($config->path, '/') . '/';
22+
$fileName = $this->request->get('fileName');
23+
$file = $path . $fileName;
24+
25+
if (!empty($fileName)) {
26+
if ((is_dir($path) || @mkdir($path, 0777)) && is_writable($path)) {
27+
$handle = fopen($file, 'wb');
28+
if ($handle && fwrite($handle, $content)) {
29+
fclose($handle);
30+
$this->widget('Widget_Notice')->set(_t('备份文件 ' . $fileName . ' 已创建'), 'success');
31+
} else {
32+
$this->widget('Widget_Notice')->set(_t('备份文件创建失败,请检查目录权限'), 'error');
33+
}
34+
} else {
35+
$this->widget('Widget_Notice')->set(_t('文件夹创建失败或目录权限限制'), 'error');
36+
}
37+
} else {
38+
$this->widget('Widget_Notice')->set(_t('备份文件名不能为空'), 'error');
39+
}
40+
}
41+
42+
/**
43+
* 导入动作
44+
*
45+
* @access public
46+
* @return void
47+
*/
48+
public function doImport()
49+
{
50+
// 暂时不写导入功能了
51+
// $this->response->goBack();
52+
// die();
53+
54+
// 数据库对象
55+
$db = Typecho_Db::get();
56+
// 表前缀
57+
$dbPrefix = $db->getPrefix();
58+
$prefixLength = strlen($dbPrefix);
59+
// 数据表
60+
$dropTable = 'DROP TABLE';
61+
$resource = $db->fetchAll($db->query('SHOW TABLES'));
62+
foreach ($resource as $value) {
63+
foreach ($value as $tableName) {
64+
if ($dbPrefix == substr($tableName, 0, $prefixLength)) {
65+
$dropTable .= ' `' . $tableName . '`, ';
66+
}
67+
}
68+
}
69+
$dropTable = rtrim($dropTable, ', ') . ';';
70+
71+
// 获取备份目录并设置文件
72+
$config = Typecho_Widget::widget('Widget_Options')->plugin('Export');
73+
$path = __TYPECHO_ROOT_DIR__ . '/' . trim($config->path, '/') . '/';
74+
75+
$bid = $this->request->get('bid');
76+
$deleteCount = 0;
77+
$scripts = '';
78+
79+
if ($bid) {
80+
$imports = is_array($bid) ? $bid : array($bid);
81+
82+
foreach ($imports as $import) {
83+
$scripts .= file_get_contents($path . $import);
84+
$deleteCount ++;
85+
}
86+
87+
// 删除存在的同名数据表
88+
$db->query($dropTable, Typecho_Db::WRITE);
89+
90+
$scripts = explode(";\r\n", $scripts);
91+
foreach ($scripts as $script) {
92+
$script = trim($script);
93+
if ($script) {
94+
$db->query($script, Typecho_Db::WRITE);
95+
}
96+
}
97+
}
98+
99+
$this->widget('Widget_Notice')->set($deleteCount > 0 ? _t('备份已经被导入') : _t('没有备份被导入'),
100+
$deleteCount > 0 ? 'success' : 'notice');
101+
}
102+
103+
/**
104+
* 删除备份
105+
*
106+
* @access public
107+
* @return void
108+
*/
109+
public function doDelete()
110+
{
111+
// 获取备份目录并设置文件
112+
$config = Typecho_Widget::widget('Widget_Options')->plugin('Export');
113+
$path = __TYPECHO_ROOT_DIR__ . '/' . trim($config->path, '/') . '/';
114+
115+
$bid = $this->request->get('bid');
116+
$deleteCount = 0;
117+
118+
if ($bid) {
119+
$backups = is_array($bid) ? $bid : array($bid);
120+
121+
foreach ($backups as $backup) {
122+
@unlink($path . $backup);
123+
$deleteCount ++;
124+
}
125+
}
126+
127+
$this->widget('Widget_Notice')->set($deleteCount > 0 ? _t('备份已经被删除') : _t('没有备份被删除'),
128+
$deleteCount > 0 ? 'success' : 'notice');
129+
}
130+
131+
/**
132+
* 构建SQL语句
133+
*
134+
* @access public
135+
* @param array $tables 数据表数组
136+
* @return string $sql SQL语句
137+
*/
138+
public function getSql(array $tables)
139+
{
140+
// 数据库对象
141+
$db = Typecho_Db::get();
142+
143+
// SQL语句
144+
$sql = '-- Typecho Backup SQL' . "\r\n"
145+
. '-- 程序版本: ' . Typecho_Common::VERSION . "\r\n"
146+
. '--' . "\r\n"
147+
. '-- 备份工具: Export' . "\r\n"
148+
. '-- 插件作者: ShingChi' . "\r\n"
149+
. '-- 主页链接: http://lcz.me' . "\r\n"
150+
. '-- 生成日期: ' . date('Y 年 m 月 d 日', Typecho_Date::gmtTime()) . "\r\n\r\n";
151+
152+
// 循环构建每张表的SQL语句
153+
foreach ($tables as $table) {
154+
// 创建表语句
155+
$createSql = '';
156+
// 插入记录语句
157+
$insertSql = '';
158+
159+
// 创建表注释
160+
$createSql .= '-- --------------------------------------------------------' . "\r\n\r\n"
161+
. '--' . "\r\n"
162+
. '-- 表的结构 `' . $table . "`\r\n"
163+
. '--' . "\r\n\r\n";
164+
165+
/* 表结构 */
166+
$replace = 'CREATE TABLE IF NOT EXISTS';
167+
$showTable = $db->fetchRow($db->query('SHOW CREATE TABLE ' . $table));
168+
$createTable = $showTable['Create Table'];
169+
$createSql .= str_replace('CREATE TABLE', $replace, $createTable) . ';' . "\r\n\r\n";
170+
171+
/* 表记录 */
172+
$rows = $db->fetchAll($db->select()->from($table));
173+
if ($rows) {
174+
// 字段组合SQL语句
175+
$fieldText = '';
176+
177+
// 值的组合SQL语句
178+
$recordText = '';
179+
180+
// 所有记录
181+
$records = array();
182+
183+
// 插入注释
184+
$insertSql .= '--' . "\r\n"
185+
. '-- 转存表中的数据 `' . $table . "`\r\n"
186+
. '--' . "\r\n\r\n";
187+
188+
// 组合字段语句
189+
foreach ($rows[0] as $key => $value) {
190+
$fieldText .= '`' . $key . '`, ';
191+
}
192+
$fieldText = rtrim($fieldText, ', ');
193+
$insertSql .= 'INSERT INTO ' . $table . ' (' . $fieldText . ') VALUES' . "\r\n";
194+
195+
// 组合一条记录的语法
196+
foreach ($rows as $k => $row) {
197+
$records[$k] = '';
198+
foreach ($row as $record) {
199+
$records[$k] .= isset($record) ? '\'' . mysql_escape_string($record) . '\', ' : 'NULL, ';
200+
}
201+
$records[$k] = rtrim($records[$k], ', ');
202+
}
203+
204+
// 组合所有记录的语法
205+
foreach ($records as $val) {
206+
$recordText .= '(' . $val . '),' . "\r\n";
207+
}
208+
$recordText = rtrim($recordText, ",\r\n") . ";\r\n\r\n";
209+
$insertSql .= $recordText;
210+
}
211+
212+
$sql .= $createSql . $insertSql;
213+
}
214+
215+
return $sql;
216+
}
217+
218+
/**
219+
* 绑定动作
220+
*
221+
* @access public
222+
* @return void
223+
*/
224+
public function action()
225+
{
226+
$this->widget('Widget_User')->pass('administrator');
227+
$this->on($this->request->is('export'))->doExport();
228+
$this->on($this->request->is('import'))->doImport();
229+
$this->on($this->request->is('delete'))->doDelete();
230+
$this->response->goBack();
231+
}
232+
}

Export/Plugin.php

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
<?php
2+
/**
3+
* 数据备份
4+
*
5+
* @package Export
6+
* @author ShingChi
7+
* @version 1.0.0
8+
* @link http://lcz.me
9+
*/
10+
class Export_Plugin implements Typecho_Plugin_Interface
11+
{
12+
/**
13+
* 激活插件方法,如果激活失败,直接抛出异常
14+
*
15+
* @access public
16+
* @return void
17+
* @throws Typecho_Plugin_Exception
18+
*/
19+
public static function activate()
20+
{
21+
Helper::addAction('export', 'Export_Action');
22+
Helper::addPanel(1, 'Export/panel.php', _t('数据备份'), _t('数据备份'), 'administrator');
23+
24+
return _t('插件已经激活,请设置插件以正常使用!');
25+
}
26+
27+
/**
28+
* 禁用插件方法,如果禁用失败,直接抛出异常
29+
*
30+
* @static
31+
* @access public
32+
* @return void
33+
* @throws Typecho_Plugin_Exception
34+
*/
35+
public static function deactivate()
36+
{
37+
Helper::removeAction('export');
38+
Helper::removePanel(1, 'Export/panel.php');
39+
}
40+
41+
/**
42+
* 获取插件配置面板
43+
*
44+
* @access public
45+
* @param Typecho_Widget_Helper_Form $form 配置面板
46+
* @return void
47+
*/
48+
public static function config(Typecho_Widget_Helper_Form $form){
49+
$path = new Typecho_Widget_Helper_Form_Element_Text(
50+
'path', NULL, '/usr/plugins/Export/backup',
51+
_t('备份文件夹'),
52+
_t('备份文件夹默认在插件目录下的 backup,路径规则请以 Typecho 根目录为准,如:/usr/backup<br>请正确设置目录权限,以便正常插件正常运行')
53+
);
54+
$form->addInput($path->addRule('required', _t('备份文件夹不能为空')));
55+
}
56+
57+
/**
58+
* 个人用户的配置面板
59+
*
60+
* @access public
61+
* @param Typecho_Widget_Helper_Form $form
62+
* @return void
63+
*/
64+
public static function personalConfig(Typecho_Widget_Helper_Form $form){}
65+
}

Export/README.md

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
## 插件说明 ##
2+
3+
已支持导入功能,但操作时,务必先备份,切记!

0 commit comments

Comments
 (0)