mirror of
https://github.com/kokororin/typecho-plugin-Access.git
synced 2024-12-27 13:20:54 +08:00
160 lines
6.1 KiB
PHP
160 lines
6.1 KiB
PHP
<?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 public
|
||
* @return bool
|
||
* @throws Exception
|
||
*/
|
||
public function exists()
|
||
{
|
||
$prefix = $this->db->getPrefix();
|
||
if ($this->db->fetchRow($this->db->query("SHOW TABLES LIKE '{$prefix}access';", Typecho_Db::READ))) {
|
||
return true;
|
||
}
|
||
if ($this->db->fetchRow($this->db->query("SHOW TABLES LIKE '{$prefix}access_log';", Typecho_Db::READ))) {
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* 显示旧版本数据数量
|
||
*
|
||
* @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();
|
||
}
|
||
}
|