mirror of
https://github.com/kokororin/typecho-plugin-Access.git
synced 2024-12-26 12:50:36 +08:00
feat: independent migration route from plugin active method
This commit is contained in:
parent
5ea4a3d070
commit
0f80487bad
@ -43,6 +43,10 @@ class Access_Core
|
||||
$ipdbPath = dirname(__file__).'/lib/ipipfree.ipdb';
|
||||
$this->ipdb = new Access_IpDb($ipdbPath);
|
||||
switch ($this->request->get('action')) {
|
||||
case 'migration':
|
||||
$this->action = 'migration';
|
||||
$this->title = _t('数据迁移');
|
||||
break;
|
||||
case 'logs':
|
||||
$this->action = 'logs';
|
||||
$this->title = _t('访问日志');
|
||||
|
140
Access_Migration.php
Normal file
140
Access_Migration.php
Normal file
@ -0,0 +1,140 @@
|
||||
<?php
|
||||
if (!defined('__ACCESS_PLUGIN_ROOT__')) {
|
||||
throw new Exception('Bootstrap file not found');
|
||||
}
|
||||
|
||||
class Access_Migration {
|
||||
/**
|
||||
* 允许访问的业务函数名及其对应的允许访问方法
|
||||
* @var string[]
|
||||
*/
|
||||
private static $rpcTypes = [
|
||||
'overview' => 'GET',
|
||||
'migrate' => 'POST',
|
||||
];
|
||||
|
||||
private $config;
|
||||
private $db;
|
||||
private $request;
|
||||
|
||||
public function __construct($request) {
|
||||
$this->db = Typecho_Db::get();
|
||||
$this->request = $request;
|
||||
$this->config = Typecho_Widget::widget('Widget_Options')->plugin('Access');
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示旧版本数据数量
|
||||
*
|
||||
* @access private
|
||||
* @return ?array
|
||||
* @throws Exception
|
||||
*/
|
||||
private function overview()
|
||||
{
|
||||
$resp = [ 'total' => 0 ];
|
||||
$prefix = $this->db->getPrefix();
|
||||
// 统计 v1 版本数据
|
||||
if ($this->db->fetchRow($this->db->query("SHOW TABLES LIKE '{$prefix}access';", Typecho_Db::READ))) {
|
||||
$resp['v1'] = $this->db->fetchRow($this->db->select('COUNT(1) AS cnt')->from('table.access'))['cnt'];
|
||||
$resp['total'] += $resp['v1'];
|
||||
}
|
||||
// 统计 v2 版本数据
|
||||
if ($this->db->fetchRow($this->db->query("SHOW TABLES LIKE '{$prefix}access_log';", Typecho_Db::READ))) {
|
||||
$resp['v2'] = intval($this->db->fetchRow($this->db->select('COUNT(1) AS cnt')->from('table.access_log'))['cnt']);
|
||||
$resp['total'] += $resp['v2'];
|
||||
}
|
||||
return $resp;
|
||||
}
|
||||
|
||||
/**
|
||||
* 迁移旧版本数据,单次1000条
|
||||
*
|
||||
* @access private
|
||||
* @return ?array
|
||||
* @throws Exception
|
||||
*/
|
||||
private function migrate()
|
||||
{
|
||||
$resp = [ 'count' => 0, 'remain' => 0 ];
|
||||
$step = 1000;
|
||||
$prefix = $this->db->getPrefix();
|
||||
// 迁移 v1 版本数据
|
||||
if ($this->db->fetchRow($this->db->query("SHOW TABLES LIKE '{$prefix}access';", Typecho_Db::READ))) {
|
||||
$remain = intval($this->db->fetchRow($this->db->select('COUNT(1) AS cnt')->from('table.access'))['cnt']);
|
||||
if ($resp['count'] === 0) {
|
||||
$rows = $this->db->fetchAll($this->db->select()->from('table.access')->limit($step));
|
||||
foreach ($rows as $row) {
|
||||
$id = $row['id'];
|
||||
unset($row['id']);
|
||||
$ua = new Access_UA($row['ua']);
|
||||
$row['browser_id' ] = $ua->getBrowserID();
|
||||
$row['browser_version' ] = $ua->getBrowserVersion();
|
||||
$row['os_id' ] = $ua->getOSID();
|
||||
$row['os_version' ] = $ua->getOSVersion();
|
||||
$row['path' ] = parse_url($row['url'], PHP_URL_PATH);
|
||||
$row['query_string' ] = parse_url($row['url'], PHP_URL_QUERY);
|
||||
$row['ip' ] = $row['ip'];
|
||||
$row['entrypoint' ] = $row['referer'];
|
||||
$row['entrypoint_domain'] = $row['referer_domain'];
|
||||
$row['time' ] = $row['date'];
|
||||
$row['robot' ] = $ua->isRobot() ? 1 : 0;
|
||||
$row['robot_id' ] = $ua->getRobotID();
|
||||
$row['robot_version' ] = $ua->getRobotVersion();
|
||||
unset($row['date']);
|
||||
$this->db->query($this->db->insert('table.access_logs')->rows($row));
|
||||
$resp['count'] += 1;
|
||||
$this->db->query($this->db->delete('table.access')->where('id = ?', $id));
|
||||
$remain -= 1;
|
||||
}
|
||||
}
|
||||
if ($remain === 0) {
|
||||
$this->db->query("DROP TABLE `{$prefix}access`;", Typecho_Db::WRITE);
|
||||
}
|
||||
$resp['remain'] += $remain;
|
||||
}
|
||||
// 迁移 v2 版本数据
|
||||
if ($this->db->fetchRow($this->db->query("SHOW TABLES LIKE '{$prefix}access_log';", Typecho_Db::READ))) {
|
||||
$remain = intval($this->db->fetchRow($this->db->select('COUNT(1) AS cnt')->from('table.access_log'))['cnt']);
|
||||
if ($resp['count'] === 0) {
|
||||
$rows = $this->db->fetchAll($this->db->select()->from('table.access_log')->limit($step));
|
||||
foreach ($rows as $row) {
|
||||
$id = $row['id'];
|
||||
unset($row['id']);
|
||||
$row['ip'] = long2ip($row['ip']);
|
||||
$this->db->query($this->db->insert('table.access_logs')->rows($row));
|
||||
$resp['count'] += 1;
|
||||
$this->db->query($this->db->delete('table.access_log')->where('id = ?', $id));
|
||||
$remain -= 1;
|
||||
}
|
||||
}
|
||||
if ($remain === 0) {
|
||||
$this->db->query("DROP TABLE `{$prefix}access_log`;", Typecho_Db::WRITE);
|
||||
}
|
||||
$resp['remain'] += $remain;
|
||||
}
|
||||
return $resp;
|
||||
}
|
||||
|
||||
/**
|
||||
* 业务调度入口
|
||||
*
|
||||
* @access public
|
||||
* @param string rpcType 调用过程类型
|
||||
* @return ?array
|
||||
* @throws Exception
|
||||
*/
|
||||
public function invoke(string $rpcType): ?array {
|
||||
if(!method_exists($this, $rpcType) || !array_key_exists($rpcType, Access_Migration::$rpcTypes))
|
||||
throw new Exception('Bad Request', 400);
|
||||
$method = Access_Migration::$rpcTypes[$rpcType];
|
||||
if (
|
||||
($method === 'GET' && !$this->request->isGet())
|
||||
|| ($method === 'POST' && !$this->request->isPost())
|
||||
|| ($method === 'PUT' && !$this->request->isPut())
|
||||
) {
|
||||
throw new Exception('Method Not Allowed', 405);
|
||||
}
|
||||
return $this->$rpcType();
|
||||
}
|
||||
}
|
21
Action.php
21
Action.php
@ -35,6 +35,27 @@ class Access_Action extends Typecho_Widget implements Widget_Interface_Do
|
||||
}
|
||||
}
|
||||
|
||||
public function migration() {
|
||||
try {
|
||||
$this->checkAuth(); # 鉴权
|
||||
$rpcType = $this->request->get('rpc'); # 业务类型
|
||||
$logs = new Access_Migration($this->request);
|
||||
$data = $logs->invoke($rpcType); # 进行业务分发并调取数据
|
||||
$errCode = 0;
|
||||
$errMsg = 'ok';
|
||||
} catch (Exception $e) {
|
||||
$data = null;
|
||||
$errCode = $e->getCode();
|
||||
$errMsg = $e->getMessage();
|
||||
}
|
||||
|
||||
$this->response->throwJson([
|
||||
'code' => $errCode,
|
||||
'message' => $errMsg,
|
||||
'data' => $data
|
||||
]);
|
||||
}
|
||||
|
||||
public function logs() {
|
||||
try {
|
||||
$this->checkAuth(); # 鉴权
|
||||
|
45
Plugin.php
45
Plugin.php
@ -24,6 +24,7 @@ class Access_Plugin implements Typecho_Plugin_Interface
|
||||
$msg = Access_Plugin::install();
|
||||
Helper::addPanel(1, self::$panel, _t('Access控制台'), _t('Access插件控制台'), 'subscriber');
|
||||
Helper::addRoute("access_track_gif", "/access/log/track.gif", "Access_Action", 'writeLogs');
|
||||
Helper::addRoute("access_migration", "/access/migration", "Access_Action", 'migration');
|
||||
Helper::addRoute("access_logs", "/access/logs", "Access_Action", 'logs');
|
||||
Helper::addRoute('access_statistic_view', '/access/statistic/view', 'Access_Action', 'statistic');
|
||||
Typecho_Plugin::factory('Widget_Archive')->beforeRender = array('Access_Plugin', 'backend');
|
||||
@ -127,50 +128,6 @@ class Access_Plugin implements Typecho_Plugin_Interface
|
||||
}
|
||||
$msg = _t('成功创建数据表,插件启用成功,') . $configLink;
|
||||
}
|
||||
# 处理旧版本数据
|
||||
if ($db->fetchRow($db->query("SHOW TABLES LIKE '{$prefix}access';", Typecho_Db::READ))) {
|
||||
$rows = $db->fetchAll($db->select()->from('table.access'));
|
||||
foreach ($rows as $row) {
|
||||
$ua = new Access_UA($row['ua']);
|
||||
$time = Helper::options()->gmtTime + (Helper::options()->timezone - Helper::options()->serverTimezone);
|
||||
$row['browser_id' ] = $ua->getBrowserID();
|
||||
$row['browser_version' ] = $ua->getBrowserVersion();
|
||||
$row['os_id' ] = $ua->getOSID();
|
||||
$row['os_version' ] = $ua->getOSVersion();
|
||||
$row['path' ] = parse_url($row['url'], PHP_URL_PATH);
|
||||
$row['query_string' ] = parse_url($row['url'], PHP_URL_QUERY);
|
||||
$row['ip' ] = $row['ip'];
|
||||
$row['entrypoint' ] = $row['referer'];
|
||||
$row['entrypoint_domain'] = $row['referer_domain'];
|
||||
$row['time' ] = $row['date'];
|
||||
$row['robot' ] = $ua->isRobot() ? 1 : 0;
|
||||
$row['robot_id' ] = $ua->getRobotID();
|
||||
$row['robot_version' ] = $ua->getRobotVersion();
|
||||
unset($row['date']);
|
||||
try {
|
||||
$db->query($db->insert('table.access_logs')->rows($row));
|
||||
} catch (Typecho_Db_Exception $e) {
|
||||
if ($e->getCode() != 23000)
|
||||
throw new Typecho_Plugin_Exception(_t('导入旧版数据失败,插件启用失败,错误信息:%s。', $e->getMessage()));
|
||||
}
|
||||
}
|
||||
$db->query("DROP TABLE `{$prefix}access`;", Typecho_Db::WRITE);
|
||||
$msg = _t('成功创建数据表并更新数据,插件启用成功,') . $configLink;
|
||||
}
|
||||
if ($db->fetchRow($db->query("SHOW TABLES LIKE '{$prefix}access_log';", Typecho_Db::READ))) {
|
||||
$rows = $db->fetchAll($db->select()->from('table.access_log'));
|
||||
foreach ($rows as $row) {
|
||||
$row['ip'] = long2ip($row['ip']);
|
||||
try {
|
||||
$db->query($db->insert('table.access_logs')->rows($row));
|
||||
} catch (Typecho_Db_Exception $e) {
|
||||
if ($e->getCode() != 23000)
|
||||
throw new Typecho_Plugin_Exception(_t('导入旧版数据失败,插件启用失败,错误信息:%s。', $e->getMessage()));
|
||||
}
|
||||
}
|
||||
$db->query("DROP TABLE `{$prefix}access_log`;", Typecho_Db::WRITE);
|
||||
$msg = _t('成功创建数据表并更新数据,插件启用成功,') . $configLink;
|
||||
}
|
||||
return $msg;
|
||||
} catch (Typecho_Db_Exception $e) {
|
||||
throw new Typecho_Plugin_Exception(_t('数据表建立失败,插件启用失败,错误信息:%s。', $e->getMessage()));
|
||||
|
13
page/console.js
Normal file
13
page/console.js
Normal file
@ -0,0 +1,13 @@
|
||||
$().ready(function () {
|
||||
$.ajax({
|
||||
url: "/access/migration",
|
||||
method: "get",
|
||||
dataType: "json",
|
||||
data: { rpc: 'overview' },
|
||||
success: function (res) {
|
||||
if (res.data.total > 0) {
|
||||
$('#migration-tab-li').show();
|
||||
}
|
||||
},
|
||||
});
|
||||
});
|
@ -5,6 +5,7 @@ include 'menu.php';
|
||||
require_once __DIR__ . '/../Access_Bootstrap.php';
|
||||
$access = new Access_Core();
|
||||
?>
|
||||
<script defer src="<?php $options->pluginUrl('Access/page/console.js')?>"></script>
|
||||
<div class="main">
|
||||
<div class="body container">
|
||||
<div class="typecho-page-title">
|
||||
@ -15,6 +16,7 @@ $access = new Access_Core();
|
||||
<ul class="typecho-option-tabs fix-tabs clearfix">
|
||||
<li<?=($access->action == 'overview' ? ' class="current"' : '')?>><a href="<?php $options->adminUrl('extending.php?panel=' . Access_Plugin::$panel . '&action=overview'); ?>"><?php _e('访问概览'); ?></a></li>
|
||||
<li<?=($access->action == 'logs' ? ' class="current"' : '')?>><a href="<?php $options->adminUrl('extending.php?panel=' . Access_Plugin::$panel . '&action=logs'); ?>"><?php _e('访问日志'); ?></a></li>
|
||||
<li<?=($access->action == 'migration' ? ' class="current"' : '')?> style="display: none" id="migration-tab-li"><a href="<?php $options->adminUrl('extending.php?panel=' . Access_Plugin::$panel . '&action=migration'); ?>"><?php _e('数据迁移'); ?></a></li>
|
||||
<li><a href="<?php $options->adminUrl('options-plugin.php?config=Access') ?>"><?php _e('插件设置'); ?></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
7
page/routes/migration/index.css
Normal file
7
page/routes/migration/index.css
Normal file
@ -0,0 +1,7 @@
|
||||
.typecho-access-migration-main {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.typecho-access-migration-summary {
|
||||
margin: 20px 0;
|
||||
}
|
36
page/routes/migration/index.js
Normal file
36
page/routes/migration/index.js
Normal file
@ -0,0 +1,36 @@
|
||||
$(document).ready(function () {
|
||||
function start() {
|
||||
$('body').loadingModal({ text: '正在准备迁移...', backgroundColor: '#292d33' }).show();
|
||||
$.ajax({
|
||||
url: "/access/migration",
|
||||
method: "post",
|
||||
dataType: "json",
|
||||
data: { rpc: 'migrate' },
|
||||
success: function (res) {
|
||||
if (res.code === 0) {
|
||||
if (res.data.remain === 0) {
|
||||
$('body').loadingModal('hide');
|
||||
} else {
|
||||
$('body').loadingModal('text', '迁移中,剩余' + res.data.remain + '条等待迁移...');
|
||||
start();
|
||||
}
|
||||
$('#ancient-logs-count').text(res.data.remain);
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
$('[data-action="migrate"]').click(function() {
|
||||
start();
|
||||
});
|
||||
|
||||
$.ajax({
|
||||
url: "/access/migration",
|
||||
method: "get",
|
||||
dataType: "json",
|
||||
data: { rpc: 'overview' },
|
||||
success: function (res) {
|
||||
$('#ancient-logs-count').text(res.data.total);
|
||||
},
|
||||
});
|
||||
});
|
17
page/routes/migration/index.php
Normal file
17
page/routes/migration/index.php
Normal file
@ -0,0 +1,17 @@
|
||||
<script src="<?php $options->pluginUrl('Access/page/components/sweetalert/index.js')?>"></script>
|
||||
<link rel="stylesheet" href="<?php $options->pluginUrl('Access/page/components/loadingmodal/index.css')?>">
|
||||
<script defer src="<?php $options->pluginUrl('Access/page/components/loadingmodal/index.js')?>"></script>
|
||||
<link rel="stylesheet" href="<?php $options->pluginUrl('Access/page/routes/migration/index.css')?>">
|
||||
<script defer src="<?php $options->pluginUrl('Access/page/routes/migration/index.js')?>"></script>
|
||||
|
||||
<div class="col-mb-12">
|
||||
<div class="typecho-access-migration-main">
|
||||
<div class="typecho-access-migration-summary">
|
||||
<span>存在历史数据:</span>
|
||||
<span id="ancient-logs-count">loading</span>
|
||||
<span>条</span>
|
||||
</div>
|
||||
|
||||
<button data-action="migrate" type="button" class="btn btn-m primary"><?php _e('开始迁移'); ?></button>
|
||||
</div>
|
||||
</div>
|
Loading…
Reference in New Issue
Block a user