2015-12-05 11:09:31 +08:00
< ? 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 ;
2016-03-28 14:45:00 +08:00
public $logs = array ();
2015-12-05 11:09:31 +08:00
public $overview = array ();
public function __construct ()
{
2016-03-28 14:45:00 +08:00
$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 ();
2015-12-05 11:09:31 +08:00
$this -> pageSize = $this -> config -> pageSize ;
2016-03-28 14:45:00 +08:00
$this -> isDrop = $this -> config -> isDrop ;
if ( $this -> pageSize == null || $this -> isDrop == null )
{
2015-12-05 11:09:31 +08:00
throw new Typecho_Plugin_Exception ( '请先设置插件!' );
}
2016-03-28 14:45:00 +08:00
switch ( $this -> request -> get ( 'action' ))
{
2015-12-05 11:09:31 +08:00
case 'logs' :
default :
$this -> action = 'logs' ;
2016-03-28 14:45:00 +08:00
$this -> title = '访问日志' ;
2015-12-05 11:09:31 +08:00
$this -> parseLogs ();
break ;
case 'overview' :
$this -> action = 'overview' ;
2016-03-28 14:45:00 +08:00
$this -> title = '访问概览' ;
2015-12-05 11:09:31 +08:00
$this -> parseOverview ();
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 ()
{
2016-03-28 14:45:00 +08:00
if ( ! ( self :: $_instance instanceof self ))
{
2015-12-05 11:09:31 +08:00
self :: $_instance = new self ();
}
return self :: $_instance ;
}
public function parseUA ( $ua )
{
$os = null ;
2016-03-28 14:45:00 +08:00
if ( $this -> isSpider ( $ua ))
{
2015-12-05 11:09:31 +08:00
$os = '爬虫' ;
2016-03-28 14:45:00 +08:00
}
elseif ( preg_match ( '/Windows NT 6.0/i' , $ua ))
{
2015-12-05 11:09:31 +08:00
$os = " Windows Vista " ;
2016-03-28 14:45:00 +08:00
}
elseif ( preg_match ( '/Windows NT 6.1/i' , $ua ))
{
2015-12-05 11:09:31 +08:00
$os = " Windows 7 " ;
2016-03-28 14:45:00 +08:00
}
elseif ( preg_match ( '/Windows NT 6.2/i' , $ua ))
{
2015-12-05 11:09:31 +08:00
$os = " Windows 8 " ;
2016-03-28 14:45:00 +08:00
}
elseif ( preg_match ( '/Windows NT 6.3/i' , $ua ))
{
2015-12-05 11:09:31 +08:00
$os = " Windows 8.1 " ;
2016-03-28 14:45:00 +08:00
}
elseif ( preg_match ( '/Windows NT 10.0/i' , $ua ))
{
2015-12-05 11:09:31 +08:00
$os = " Windows 10 " ;
2016-03-28 14:45:00 +08:00
}
elseif ( preg_match ( '/Windows NT 5.1/i' , $ua ))
{
2015-12-05 11:09:31 +08:00
$os = " Windows XP " ;
2016-03-28 14:45:00 +08:00
}
elseif ( preg_match ( '/Windows NT 5.2/i' , $ua ) && preg_match ( '/Win64/i' , $ua ))
{
2015-12-05 11:09:31 +08:00
$os = " Windows XP 64 bit " ;
2016-03-28 14:45:00 +08:00
}
elseif ( preg_match ( '/Android ([0-9.]+)/i' , $ua , $matches ))
{
2015-12-05 11:09:31 +08:00
$os = " Android " . $matches [ 1 ];
2016-03-28 14:45:00 +08:00
}
elseif ( preg_match ( '/iPhone OS ([_0-9]+)/i' , $ua , $matches ))
{
2015-12-05 11:09:31 +08:00
$os = 'iPhone ' . $matches [ 1 ];
2016-03-28 14:45:00 +08:00
}
elseif ( preg_match ( '/Ubuntu/i' , $ua , $matches ))
{
2015-12-05 11:09:31 +08:00
$os = 'Ubuntu ' ;
2016-03-28 14:45:00 +08:00
}
elseif ( preg_match ( '/Mac OS X ([0-9_]+)/i' , $ua , $matches ))
{
2015-12-05 11:09:31 +08:00
$os = 'Mac OS ' . $matches [ 1 ];
2016-03-28 14:45:00 +08:00
}
elseif ( preg_match ( '/Linux/i' , $ua , $matches ))
{
2015-12-05 11:09:31 +08:00
$os = 'Linux' ;
2016-03-28 14:45:00 +08:00
}
else
{
2015-12-05 11:09:31 +08:00
$os = '未知' ;
}
2016-03-28 14:45:00 +08:00
if ( $this -> isSpider ( $ua ))
{
2015-12-05 11:09:31 +08:00
$browser = '爬虫' ;
2016-03-28 14:45:00 +08:00
}
elseif ( preg_match ( '#(Camino|Chimera)[ /]([a-zA-Z0-9.]+)#i' , $ua , $matches ))
{
2015-12-05 11:09:31 +08:00
$browser = 'Camino ' . $matches [ 2 ];
2016-03-28 14:45:00 +08:00
}
elseif ( preg_match ( '#SE 2([a-zA-Z0-9.]+)#i' , $ua , $matches ))
{
2015-12-05 11:09:31 +08:00
$browser = '搜狗浏览器 2' . $matches [ 1 ];
2016-03-28 14:45:00 +08:00
}
elseif ( preg_match ( '#360([a-zA-Z0-9.]+)#i' , $ua , $matches ))
{
2015-12-05 11:09:31 +08:00
$browser = '360浏览器 ' . $matches [ 1 ];
2016-03-28 14:45:00 +08:00
}
elseif ( preg_match ( '#Maxthon( |\/)([a-zA-Z0-9.]+)#i' , $ua , $matches ))
{
2015-12-05 11:09:31 +08:00
$browser = 'Maxthon ' . $matches [ 2 ];
2016-03-28 14:45:00 +08:00
}
elseif ( preg_match ( '#Chrome/([a-zA-Z0-9.]+)#i' , $ua , $matches ))
{
2015-12-05 11:09:31 +08:00
$browser = 'Chrome ' . $matches [ 1 ];
2016-03-28 14:45:00 +08:00
}
elseif ( preg_match ( '#XiaoMi/MiuiBrowser/([0-9.]+)#i' , $ua , $matches ))
{
2015-12-05 11:09:31 +08:00
$browser = '小米浏览器 ' . $matches [ 1 ];
2016-03-28 14:45:00 +08:00
}
elseif ( preg_match ( '#Safari/([a-zA-Z0-9.]+)#i' , $ua , $matches ))
{
2015-12-05 11:09:31 +08:00
$browser = 'Safari ' . $matches [ 1 ];
2016-03-28 14:45:00 +08:00
}
elseif ( preg_match ( '#opera mini#i' , $ua ))
{
2015-12-05 11:09:31 +08:00
preg_match ( '#Opera/([a-zA-Z0-9.]+)#i' , $ua , $matches );
$browser = 'Opera Mini ' . $matches [ 1 ];
2016-03-28 14:45:00 +08:00
}
elseif ( preg_match ( '#Opera.([a-zA-Z0-9.]+)#i' , $ua , $matches ))
{
2015-12-05 11:09:31 +08:00
$browser = 'Opera ' . $matches [ 1 ];
2016-03-28 14:45:00 +08:00
}
elseif ( preg_match ( '#TencentTraveler ([a-zA-Z0-9.]+)#i' , $ua , $matches ))
{
2015-12-05 11:09:31 +08:00
$browser = '腾讯TT浏览器 ' . $matches [ 1 ];
2016-03-28 14:45:00 +08:00
}
elseif ( preg_match ( '#UCWEB([a-zA-Z0-9.]+)#i' , $ua , $matches ))
{
2015-12-05 11:09:31 +08:00
$browser = 'UCWEB ' . $matches [ 1 ];
2016-03-28 14:45:00 +08:00
}
elseif ( preg_match ( '#MSIE ([a-zA-Z0-9.]+)#i' , $ua , $matches ))
{
2015-12-05 11:09:31 +08:00
$browser = 'Internet Explorer ' . $matches [ 1 ];
2016-03-28 14:45:00 +08:00
}
elseif ( preg_match ( '#Trident#' , $ua , $matches ))
{
2015-12-05 11:09:31 +08:00
$browser = 'Internet Explorer 11' ;
2016-03-28 14:45:00 +08:00
}
elseif ( preg_match ( '#Edge/12.0#i' , $ua , $matches ))
{
2015-12-05 11:09:31 +08:00
//win10中spartan浏览器
$browser = 'Spartan' ;
2016-03-28 14:45:00 +08:00
}
elseif ( preg_match ( '#(Firefox|Phoenix|Firebird|BonEcho|GranParadiso|Minefield|Iceweasel)/([a-zA-Z0-9.]+)#i' , $ua , $matches ))
{
2015-12-05 11:09:31 +08:00
$browser = 'Firefox ' . $matches [ 2 ];
2016-03-28 14:45:00 +08:00
}
else
{
2015-12-05 11:09:31 +08:00
$browser = '未知' ;
}
2016-03-28 14:45:00 +08:00
return $os . " / " . $browser ;
2015-12-05 11:09:31 +08:00
}
public function isSpider ( $ua )
{
$ua = strtolower ( $ua );
2016-03-28 14:45:00 +08:00
if ( ! empty ( $ua ))
{
foreach ( $this -> spiderArray as $val )
{
2015-12-05 11:09:31 +08:00
$str = strtolower ( $val );
2016-03-28 14:45:00 +08:00
if ( strpos ( $ua , $str ) !== false )
{
2015-12-05 11:09:31 +08:00
return true ;
}
}
2016-03-28 14:45:00 +08:00
}
else
{
2015-12-05 11:09:31 +08:00
return false ;
}
}
protected function getWhere ( $type )
{
$where_str = '' ;
2016-03-28 14:45:00 +08:00
foreach ( $this -> spiderArray as $value )
{
2015-12-05 11:09:31 +08:00
$where_str .= " ua { 1} LIKE " . " '% { $value } %' { 2} " ;
}
$where_str = rtrim ( $where_str , '{2} ' );
2016-03-28 14:45:00 +08:00
switch ( $type )
{
2015-12-05 11:09:31 +08:00
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 ()
{
2016-03-28 14:45:00 +08:00
$type = $this -> request -> get ( 'type' , 1 );
$p = $this -> request -> get ( 'page' , 1 );
2015-12-05 11:09:31 +08:00
$offset = ( max ( intval ( $p ), 1 ) - 1 ) * $this -> pageSize ;
2016-03-28 14:45:00 +08:00
$where = $this -> getWhere ( $type );
2015-12-05 11:09:31 +08:00
$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' ;
2016-03-28 14:45:00 +08:00
$pager = new Page ( $this -> pageSize , $this -> logs [ 'rows' ], $p , 10 );
2015-12-05 11:09:31 +08:00
$this -> logs [ 'page' ] = $pager -> show ();
}
protected function parseOverview ()
{
$where = 'WHERE 1=1' ;
2016-03-28 14:45:00 +08:00
$this -> overview [ 'ip' ][ 'today' ][ 'total' ] = 0 ;
$this -> overview [ 'uv' ][ 'today' ][ 'total' ] = 0 ;
$this -> overview [ 'pv' ][ 'today' ][ 'total' ] = 0 ;
2015-12-05 11:09:31 +08:00
$this -> overview [ 'ip' ][ 'yesterday' ][ 'total' ] = 0 ;
$this -> overview [ 'uv' ][ 'yesterday' ][ 'total' ] = 0 ;
$this -> overview [ 'pv' ][ 'yesterday' ][ 'total' ] = 0 ;
2016-03-28 14:45:00 +08:00
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 " ));
2015-12-05 11:09:31 +08:00
$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 ];
}
2016-03-28 14:45:00 +08:00
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 " ));
2015-12-05 11:09:31 +08:00
$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 ];
}
2016-03-28 14:45:00 +08:00
$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 } " ));
2015-12-05 11:09:31 +08:00
2016-03-28 14:45:00 +08:00
$this -> overview [ 'chart' ][ 'title' ][ 'text' ] = date ( " Y-m-d 统计 " );
2015-12-05 11:09:31 +08:00
$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 );
2016-03-28 14:45:00 +08:00
$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 );
2015-12-05 11:09:31 +08:00
}
protected function buildObject ( $array , $quote )
{
$obj = json_encode ( $array );
$obj = str_replace ( " \" " , " ' " , $obj );
2016-03-28 14:45:00 +08:00
if ( $quote )
{
2015-12-05 11:09:31 +08:00
return $obj ;
}
2016-03-28 14:45:00 +08:00
else
{
return str_replace ( " ' " , '' , $obj );
2015-12-05 11:09:31 +08:00
}
}
}