typecho-plugin-Access/Access.php
2016-08-01 15:04:53 +08:00

295 lines
12 KiB
PHP

<?php
class Access_Extend
{
protected $db;
protected $prefix;
protected $table;
protected $config;
protected $request;
protected $pageSize;
protected $isDrop;
private static $_instance = null;
public $action;
public $title;
public $logs = array();
public $overview = array();
public $referer = array();
public function __construct()
{
$this->db = Typecho_Db::get();
$this->prefix = $this->db->getPrefix();
$this->table = $this->prefix . 'access';
$this->config = Typecho_Widget::widget('Widget_Options')->plugin('Access');
$this->request = Typecho_Request::getInstance();
$this->pageSize = $this->config->pageSize;
$this->isDrop = $this->config->isDrop;
if ($this->pageSize == null || $this->isDrop == null) {
throw new Typecho_Plugin_Exception('请先设置插件!');
}
switch ($this->request->get('action')) {
case 'logs':
default:
$this->action = 'logs';
$this->title = '访问日志';
$this->parseLogs();
break;
case 'overview':
$this->action = 'overview';
$this->title = '访问概览';
$this->parseOverview();
$this->parseReferer();
break;
}
}
public $spiderArray = array(
"TencentTraveler",
"Baiduspider",
"BaiduGame",
"Googlebot",
"msnbot",
"Sosospider+",
"Sogou web spider",
"ia_archiver",
"Yahoo! Slurp",
"YoudaoBot",
"Yahoo Slurp",
"MSNBot",
"Java (Often spam bot)",
"BaiDuSpider",
"Voila",
"Yandex bot",
"BSpider",
"twiceler",
"Sogou Spider",
"Speedy Spider",
"Google AdSense",
"Heritrix",
"Python-urllib",
"Alexa (IA Archiver)",
"Ask",
"Exabot",
"Custo",
"OutfoxBot/YodaoBot",
"yacy",
"SurveyBot",
"legs",
"lwp-trivial",
"Nutch",
"StackRambler",
"The web archive (IA Archiver)",
"Perl tool",
"MJ12bot",
"Netcraft",
"MSIECrawler",
"WGet tools",
"larbin",
"Fish search",
"crawler",
"bingbot",
);
public static function getInstance()
{
if (!(self::$_instance instanceof self)) {
self::$_instance = new self();
}
return self::$_instance;
}
public function parseUA($ua)
{
$os = null;
if ($this->isSpider($ua)) {
$os = '爬虫';
} elseif (preg_match('/Windows NT 6.0/i', $ua)) {
$os = "Windows Vista";
} elseif (preg_match('/Windows NT 6.1/i', $ua)) {
$os = "Windows 7";
} elseif (preg_match('/Windows NT 6.2/i', $ua)) {
$os = "Windows 8";
} elseif (preg_match('/Windows NT 6.3/i', $ua)) {
$os = "Windows 8.1";
} elseif (preg_match('/Windows NT 10.0/i', $ua)) {
$os = "Windows 10";
} elseif (preg_match('/Windows NT 5.1/i', $ua)) {
$os = "Windows XP";
} elseif (preg_match('/Windows NT 5.2/i', $ua) && preg_match('/Win64/i', $ua)) {
$os = "Windows XP 64 bit";
} elseif (preg_match('/Android ([0-9.]+)/i', $ua, $matches)) {
$os = "Android " . $matches[1];
} elseif (preg_match('/iPhone OS ([_0-9]+)/i', $ua, $matches)) {
$os = 'iPhone ' . $matches[1];
} elseif (preg_match('/Ubuntu/i', $ua, $matches)) {
$os = 'Ubuntu ';
} elseif (preg_match('/Mac OS X ([0-9_]+)/i', $ua, $matches)) {
$os = 'Mac OS X ' . $matches[1];
} elseif (preg_match('/Linux/i', $ua, $matches)) {
$os = 'Linux';
} else {
$os = '未知';
}
if ($this->isSpider($ua)) {
$browser = '爬虫';
} elseif (preg_match('#(Camino|Chimera)[ /]([a-zA-Z0-9.]+)#i', $ua, $matches)) {
$browser = 'Camino ' . $matches[2];
} elseif (preg_match('#SE 2([a-zA-Z0-9.]+)#i', $ua, $matches)) {
$browser = '搜狗浏览器 2' . $matches[1];
} elseif (preg_match('#360([a-zA-Z0-9.]+)#i', $ua, $matches)) {
$browser = '360浏览器 ' . $matches[1];
} elseif (preg_match('#Maxthon( |\/)([a-zA-Z0-9.]+)#i', $ua, $matches)) {
$browser = 'Maxthon ' . $matches[2];
} elseif (preg_match('#Chrome/([a-zA-Z0-9.]+)#i', $ua, $matches)) {
$browser = 'Chrome ' . $matches[1];
} elseif (preg_match('#XiaoMi/MiuiBrowser/([0-9.]+)#i', $ua, $matches)) {
$browser = '小米浏览器 ' . $matches[1];
} elseif (preg_match('#Safari/([a-zA-Z0-9.]+)#i', $ua, $matches)) {
$browser = 'Safari ' . $matches[1];
} elseif (preg_match('#opera mini#i', $ua)) {
preg_match('#Opera/([a-zA-Z0-9.]+)#i', $ua, $matches);
$browser = 'Opera Mini ' . $matches[1];
} elseif (preg_match('#Opera.([a-zA-Z0-9.]+)#i', $ua, $matches)) {
$browser = 'Opera ' . $matches[1];
} elseif (preg_match('#TencentTraveler ([a-zA-Z0-9.]+)#i', $ua, $matches)) {
$browser = '腾讯TT浏览器 ' . $matches[1];
} elseif (preg_match('#UCWEB([a-zA-Z0-9.]+)#i', $ua, $matches)) {
$browser = 'UCWEB ' . $matches[1];
} elseif (preg_match('#MSIE ([a-zA-Z0-9.]+)#i', $ua, $matches)) {
$browser = 'Internet Explorer ' . $matches[1];
} elseif (preg_match('#Trident#', $ua, $matches)) {
$browser = 'Internet Explorer 11';
} elseif (preg_match('#Edge/12.0#i', $ua, $matches)) {
//win10中spartan浏览器
$browser = 'Spartan';
} elseif (preg_match('#(Firefox|Phoenix|Firebird|BonEcho|GranParadiso|Minefield|Iceweasel)/([a-zA-Z0-9.]+)#i', $ua, $matches)) {
$browser = 'Firefox ' . $matches[2];
} else {
$browser = '未知';
}
return $os . " / " . $browser;
}
public function isSpider($ua)
{
$ua = strtolower($ua);
if (!empty($ua)) {
foreach ($this->spiderArray as $val) {
$str = strtolower($val);
if (strpos($ua, $str) !== false) {
return true;
}
}
} else {
return false;
}
}
protected function getWhere($type)
{
$where_str = '';
foreach ($this->spiderArray as $value) {
$where_str .= "ua {1} LIKE " . "'%{$value}%' {2} ";
}
$where_str = rtrim($where_str, '{2} ');
switch ($type) {
case 1:
$where = str_replace('{1}', 'NOT', $where_str);
$where = str_replace('{2}', 'and', $where);
break;
case 2:
$where = str_replace('{1}', '', $where_str);
$where = str_replace('{2}', 'or', $where);
break;
case 3:
$where = '1=1';
break;
default:
throw new Typecho_Plugin_Exception('参数不正确!');
}
return 'WHERE ' . $where;
}
protected function parseLogs()
{
$type = $this->request->get('type', 1);
$p = $this->request->get('page', 1);
$offset = (max(intval($p), 1) - 1) * $this->pageSize;
$where = $this->getWhere($type);
$this->logs['list'] = $this->db->fetchAll("SELECT * FROM {$this->table} {$where} ORDER BY id DESC LIMIT {$this->pageSize} OFFSET {$offset}");
$this->logs['rows'] = count($this->db->fetchAll("SELECT * FROM {$this->table} {$where}"));
include_once dirname(__FILE__) . '/lib/Page.php';
$pager = new Page($this->pageSize, $this->logs['rows'], $p, 10);
$this->logs['page'] = $pager->show();
}
protected function parseReferer()
{
$this->referer['url'] = $this->db->fetchAll("SELECT DISTINCT referer, COUNT(*) as count FROM {$this->table} WHERE referer <> '' GROUP BY referer ORDER BY count DESC LIMIT {$this->pageSize}");
$this->referer['domain'] = $this->db->fetchAll("SELECT DISTINCT referer_domain, COUNT(*) as count FROM {$this->table} WHERE referer_domain <> '' GROUP BY referer_domain ORDER BY count DESC LIMIT {$this->pageSize}");
}
protected function parseOverview()
{
$where = 'WHERE 1=1';
$this->overview['ip']['today']['total'] = 0;
$this->overview['uv']['today']['total'] = 0;
$this->overview['pv']['today']['total'] = 0;
$this->overview['ip']['yesterday']['total'] = 0;
$this->overview['uv']['yesterday']['total'] = 0;
$this->overview['pv']['yesterday']['total'] = 0;
for ($i = 0; $i < 24; $i++) {
$today = date("Y-m-d");
$start = strtotime(date("{$today} {$i}:00:00"));
$end = strtotime(date("{$today} {$i}:59:59"));
$this->overview['ip']['today']['hours'][] = count($this->db->fetchAll("SELECT DISTINCT ip FROM {$this->table} {$where} AND date BETWEEN {$start} AND {$end}"));
$this->overview['ip']['today']['total'] += $this->overview['ip']['today']['hours'][$i];
$this->overview['uv']['today']['hours'][] = count($this->db->fetchAll("SELECT DISTINCT ip,ua FROM {$this->table} {$where} AND date BETWEEN {$start} AND {$end}"));
$this->overview['uv']['today']['total'] += $this->overview['uv']['today']['hours'][$i];
$this->overview['pv']['today']['hours'][] = count($this->db->fetchAll("SELECT ip FROM {$this->table} {$where} AND date BETWEEN {$start} AND {$end}"));
$this->overview['pv']['today']['total'] += $this->overview['pv']['today']['hours'][$i];
}
for ($i = 0; $i < 24; $i++) {
$yesterday = date("Y-m-d", time() - 24 * 60 * 60);
$start = strtotime(date("{$yesterday} {$i}:00:00"));
$end = strtotime(date("{$yesterday} {$i}:59:59"));
$this->overview['ip']['yesterday']['hours'][] = count($this->db->fetchAll("SELECT DISTINCT ip FROM {$this->table} {$where} AND date BETWEEN {$start} AND {$end}"));
$this->overview['ip']['yesterday']['total'] += $this->overview['ip']['yesterday']['hours'][$i];
$this->overview['uv']['yesterday']['hours'][] = count($this->db->fetchAll("SELECT DISTINCT ip,ua FROM {$this->table} {$where} AND date BETWEEN {$start} AND {$end}"));
$this->overview['uv']['yesterday']['total'] += $this->overview['uv']['yesterday']['hours'][$i];
$this->overview['pv']['yesterday']['hours'][] = count($this->db->fetchAll("SELECT ip FROM {$this->table} {$where} AND date BETWEEN {$start} AND {$end}"));
$this->overview['pv']['yesterday']['total'] += $this->overview['pv']['yesterday']['hours'][$i];
}
$this->overview['ip']['all']['total'] = count($this->db->fetchAll("SELECT DISTINCT ip FROM {$this->table} {$where}"));
$this->overview['uv']['all']['total'] = count($this->db->fetchAll("SELECT DISTINCT ip,ua FROM {$this->table} {$where}"));
$this->overview['pv']['all']['total'] = count($this->db->fetchAll("SELECT ip FROM {$this->table} {$where}"));
$this->overview['chart']['title']['text'] = date("Y-m-d 统计");
$this->overview['chart']['xAxis']['categories'] = $this->buildObject(array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23), true);
$this->overview['chart']['series']['pv'] = $this->buildObject($this->overview['pv']['today']['hours'], false);
$this->overview['chart']['series']['uv'] = $this->buildObject($this->overview['uv']['today']['hours'], false);
$this->overview['chart']['series']['ip'] = $this->buildObject($this->overview['ip']['today']['hours'], false);
}
protected function buildObject($array, $quote)
{
$obj = json_encode($array);
$obj = str_replace("\"", "'", $obj);
if ($quote) {
return $obj;
} else {
return str_replace("'", '', $obj);
}
}
}