• R/O
  • HTTP
  • SSH
  • HTTPS

よく使われているワード(クリックで追加)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

Nucleusで簡易アクセス解析を行うためのプラグイン


ファイル情報

Rev. 3e612429589365bf6afb0392c16c6e5852bd3893
サイズ 27,868 バイト
日時 2015-07-07 00:39:46
作者 reine
ログメッセージ

ADD: IE11のUAを認識するようパターンを追加

内容

<?php
class NP_AccessAnalyze extends NucleusPlugin {
	function getName()        { return 'Access Analyze'; }
	function getAuthor()      { return 'Reine'; }
	function getURL()         { return 'http://japan.nucleuscms.org/wiki/plugins:accessanalyze'; }
	function getVersion()     { return '1.42'; }
	function getDescription() { return $this->translated('Simple access analysis plugin.'); }
	function getMinNucleusVersion() { return '350'; }
	function supportsFeature($feature) {
		switch($feature) {
			case 'SqlTablePrefix':	return 1;
			case 'SqlApi':			return 1;
			case 'HelpPage':		return 0;
			default:				return 0;
		}
	}
	
	function getEventList() {
		return array('QuickMenu'
			, 'InitSkinParse'
			, 'PostDeleteItem'
			, 'PostDeleteBlog'
			, 'PostPluginOptionsUpdate'
			, 'AdminPrePageHead');
	}
	
	/* Plugin initialize */
	function init() {
	}
	
	/* add prefix tablename */
	function tablePrefix($tablename) {
		return sql_table('NP_AccessAnalyze_' . $tablename);
	}
	
	/* Plugin install */
  	function install() {
		/* Create Option */
		$this->createOption('getBlogAdminLog', $this->translated('Do you want to get a blogAdmin logs?'), 'yesno', 'no');
		$this->createOption('delSyncLog', $this->translated('Do you want to delete the log, depending on the blog or item?'), 'yesno', 'yes');
		$this->createOption('cleardb', $this->translated('Clear database on uninstall?'), 'yesno', 'no');
		$this->createOption('quickmenu', $this->translated('Is the button added to a quick menu?'), 'yesno', 'yes');
		
		$this->createBlogOption('counterTemplate', $this->translated('Template to display the counter.'), 'textarea'
			, '<dd>Total:<%total_uv%>/<%total_pv%></dd><dd>Today:<%today_uv%>/<%today_pv%></dd><dd>Yesterday:<%yesterday_uv%>/<%yesterday_pv%></dd><dd>Week:<%week_uv%>/<%week_pv%></dd>');
		$this->createBlogOption('itemRankTemplate', $this->translated('Popular items in the list view template.'), 'textarea'
			, '<dd><a href="<%itemlink%>"><%rank%>.&nbsp;<%title%>[<%postdate%>](<%pageview%>hit/<%comments%>Comment(s))</a></dd>');
		$this->createBlogOption('initialUserView', $this->translated('The initial value of the user view counter.'), 'text', '0', 'datatype=numerical');
		$this->createBlogOption('initialPageView', $this->translated('The initial value of the page view counter.'), 'text', '0', 'datatype=numerical');
		
		/* Create Table */
		$q = "CREATE TABLE IF NOT EXISTS ".$this->tablePrefix('UserTemp')
			." (blogid INTEGER UNSIGNED NOT NULL,"
			."  userkey VARCHAR(8) NOT NULL,"
			."  ipaddr VARCHAR(40) NULL,"
			."  hostaddr VARCHAR(40) NULL,"
			."  accessdate VARCHAR(8) NULL,"
			."  PRIMARY KEY(blogid, userkey))";
		sql_query($q);
		
		$q = "CREATE TABLE IF NOT EXISTS ".$this->tablePrefix('SiteCount')
			." (blogid INTEGER UNSIGNED NOT NULL,"
			."  period VARCHAR(8) NOT NULL,"
			."  userview INTEGER UNSIGNED DEFAULT 0,"
			."  pageview INTEGER UNSIGNED DEFAULT 0,"
			."  rssview INTEGER UNSIGNED DEFAULT 0,"
			."  PRIMARY KEY(blogid, period))";
		sql_query($q);
		
		$q = "CREATE TABLE IF NOT EXISTS ".$this->tablePrefix('HourlyCount')
			." (blogid INTEGER UNSIGNED NOT NULL,"
			."  period VARCHAR(8) NOT NULL,"
			."  pageview00 INTEGER UNSIGNED DEFAULT 0, pageview01 INTEGER UNSIGNED DEFAULT 0, pageview02 INTEGER UNSIGNED DEFAULT 0,"
			."  pageview03 INTEGER UNSIGNED DEFAULT 0, pageview04 INTEGER UNSIGNED DEFAULT 0, pageview05 INTEGER UNSIGNED DEFAULT 0,"
			."  pageview06 INTEGER UNSIGNED DEFAULT 0, pageview07 INTEGER UNSIGNED DEFAULT 0, pageview08 INTEGER UNSIGNED DEFAULT 0,"
			."  pageview09 INTEGER UNSIGNED DEFAULT 0, pageview10 INTEGER UNSIGNED DEFAULT 0, pageview11 INTEGER UNSIGNED DEFAULT 0,"
			."  pageview12 INTEGER UNSIGNED DEFAULT 0, pageview13 INTEGER UNSIGNED DEFAULT 0, pageview14 INTEGER UNSIGNED DEFAULT 0,"
			."  pageview15 INTEGER UNSIGNED DEFAULT 0, pageview16 INTEGER UNSIGNED DEFAULT 0, pageview17 INTEGER UNSIGNED DEFAULT 0,"
			."  pageview18 INTEGER UNSIGNED DEFAULT 0, pageview19 INTEGER UNSIGNED DEFAULT 0, pageview20 INTEGER UNSIGNED DEFAULT 0,"
			."  pageview21 INTEGER UNSIGNED DEFAULT 0, pageview22 INTEGER UNSIGNED DEFAULT 0, pageview23 INTEGER UNSIGNED DEFAULT 0,"
			."  PRIMARY KEY(blogid, period))";
		sql_query($q);
		
		$q = "CREATE TABLE IF NOT EXISTS ".$this->tablePrefix('ItemCount')
			." (blogid INTEGER UNSIGNED NOT NULL,"
			."  period VARCHAR(8) NOT NULL,"
			."  itemid INTEGER UNSIGNED NOT NULL,"
			."  pageview INTEGER UNSIGNED DEFAULT 0,"
			."  PRIMARY KEY(blogid, period, itemid))";
		sql_query($q);
		
		$q = "CREATE TABLE IF NOT EXISTS ".$this->tablePrefix('RefererCount')
			." (blogid INTEGER UNSIGNED NOT NULL,"
			."  period VARCHAR(8) NOT NULL,"
			."  itemid INTEGER UNSIGNED NOT NULL,"
			."  referer VARCHAR(255) NOT NULL,"
			."  pageview INTEGER UNSIGNED DEFAULT 0,"
			."  PRIMARY KEY(blogid, period, itemid, referer))";
		sql_query($q);
		
		$q = "CREATE TABLE IF NOT EXISTS ".$this->tablePrefix('SearchCount')
			." (blogid INTEGER UNSIGNED NOT NULL,"
			."  period VARCHAR(8) NOT NULL,"
			."  source VARCHAR(20) NOT NULL,"
			."  searchword VARCHAR(50) NOT NULL,"
			."  pageview INTEGER UNSIGNED DEFAULT 0,"
			."  PRIMARY KEY(blogid, period, source, searchword))";
		sql_query($q);
		
		$q = "CREATE TABLE IF NOT EXISTS ".$this->tablePrefix('AgentCount')
			." (blogid INTEGER UNSIGNED NOT NULL,"
			."  period VARCHAR(8) NOT NULL,"
			."  os VARCHAR(20) NULL,"
			."  engine VARCHAR(20) NULL,"
			."  browser VARCHAR(30) NULL,"
			."  userview INTEGER UNSIGNED DEFAULT 0,"
			."  PRIMARY KEY(blogid, period, os, engine, browser))";
		sql_query($q);
	}
	
	/* Plugin uninstall */
	function uninstall() {
		/* Delete Table */
		if ($this->getOption('cleardb') == "yes") {
			sql_query("DROP TABLE IF EXISTS ".$this->tablePrefix('UserTemp'));
			sql_query("DROP TABLE IF EXISTS ".$this->tablePrefix('SiteCount'));
			sql_query("DROP TABLE IF EXISTS ".$this->tablePrefix('HourlyCount'));
			sql_query("DROP TABLE IF EXISTS ".$this->tablePrefix('ItemCount'));
			sql_query("DROP TABLE IF EXISTS ".$this->tablePrefix('RefererCount'));
			sql_query("DROP TABLE IF EXISTS ".$this->tablePrefix('SearchCount'));
			sql_query("DROP TABLE IF EXISTS ".$this->tablePrefix('AgentCount'));
		}
		/* Delete Option */
		$this->deleteOption('getBlogAdminLog');
		$this->deleteOption('delSyncLog');
		$this->deleteOption('cleardb');
		$this->deleteOption('quickmenu');
		
		$this->deleteBlogOption('counterTemplate');
		$this->deleteBlogOption('itemRankTemplate');
		$this->deleteBlogOption('initialUserView');
		$this->deleteBlogOption('initialPageView');
	}
	
	function getTableList() {
		return array(
			$this->tablePrefix('UserTemp'),
			$this->tablePrefix('SiteCount'),
			$this->tablePrefix('HourlyCount'),
			$this->tablePrefix('ItemCount'),
			$this->tablePrefix('RefererCount'),
			$this->tablePrefix('SearchCount'),
			$this->tablePrefix('AgentCount'));
	}
	
	function hasAdminArea()
	{
		return 1;
	}
	
	function doSkinVar($skinType, $mode = '', $param1 = '', $param2 = '', $param3 = '') {
		global $blogid;
		switch ($mode) {
			case 'counter':
				echo $this->createCounter();
				break;
			case 'itemrank':
				echo $this->createItemRank($param1, intval($param2), $param3);
				break;
		}
	}
	
	function event_InitSkinParse($data) {
		global $blogid, $member;
		
		if ($this->getOption('getBlogAdminLog') !== 'yes' && $member->blogAdminRights($blogid)) return;
		
		$this->getAccessLog($data['skin'], $data['type']);
	}
	
	function event_PostDeleteBlog($data) {
		if ($this->getOption('delSyncLog') === 'yes') {
			$this->deleteBlogCount($data['blogid']);
		}
	}
	
	function event_PostDeleteItem($data) {
		if ($this->getOption('delSyncLog') === 'yes') {
			$this->deleteItemCount($data['itemid']);
		}
	}
	
	function event_PostPluginOptionsUpdate($data) {
		if ($data['context'] == 'blog') {
			$this->setInitialCount($data['blogid']);
		}
	}
	
	function event_AdminPrePageHead(&$data) {
		global $CONF;
		if ($data['action'] != 'plugin_AccessAnalyze') {
			return;
		}
		$data['extrahead'] .= "\n".'<link rel="stylesheet" type="text/css" href="'.$CONF['PluginURL'].'accessanalyze/style.css" />';
	}
	
	function event_QuickMenu($data) {
		// only show when option enabled
		if ($this->getOption('quickmenu') !== 'yes') return;
		global $member;
		if (!$member->isAdmin() && !count($member->getAdminBlogs())) return;
		array_push($data['options']
			, array(
				'title' => $this->translated('AccessAnalyze'),
				'url' => $this->getAdminURL(),
				'tooltip' => $this->translated('AccessAnalyze')
			));
	}
	
	/*-------------------------------------------
	  Common Functions
	-------------------------------------------*/
	/* Language stuff */
	var $langArray;
	function translated($english) {
		if (!is_array($this->langArray)) {
			$this->langArray=array();
			$language=$this->getDirectory().'language/'.preg_replace( '[\\|/]', '', getLanguageName()).'.php';
			if (file_exists($language)) include($language);
		}
		$ret = array_key_exists($english, $this->langArray) ? $this->langArray[$english] : $english;
		return $ret;
	}
	
	/* Find a part from haystackarrayArray to needlearrayArray */
	function inArraySearch($needlearray, $haystackarray) {
		foreach ($needlearray as $n_item) {
			foreach ($haystackarray as $h_item) {
				if (stripos($h_item, $n_item) !== FALSE) return $h_item;
			}
		}
		return FALSE;
	}
	
	/* Create random code */
	function randomCode( $setLength = 8 ) {
		$rs  = '';
		$letter = array_merge (range(a,z), range(A,Z), range(0,9));
		
		// length range
		$st = 0;
		$fn = count($letter) - 1;
		
		// make random chars
		for($n = 0; $n < $setLength; $n++) $rs .= $letter[mt_rand($st, $fn)];
		return $rs;
	}
	
	/*-------------------------------------------
	  User Functions
	-------------------------------------------*/
	/* get accesslog */
	function getAccessLog($skin, $type) {
		global $CONF, $blogid, $itemid, $query, $manager;
		$blog =& $manager->getBlog($blogid);
		$logDate = explode("/", date('Ymd/H'));
		$userview = 0;
		
		// AccessValid check
		if (!$blogid) return;
		if ($type == 'error') return;
		
		// ContentType check
		if (stripos($skin->getContentType(), 'xml') !== false) {
			// rss count
			$this->setSiteCount($blogid, $logDate, 0, 0, 1);
			return;
		}

		// UniqueUser check
		$remoteaddr = serverVar('REMOTE_ADDR');
		$userkey = cookieVar('NP_AccessAnalyze_userkey');
		$valid = $this->checkUserKey($blogid, $userkey, $remoteaddr, $logDate);
		if (!$valid) {
			// userview count
			$userview = 1;
			// agent count
			$this->setAgentCount($blogid, $logDate);
			
			if (!$userkey) {
				$userkey = $this->randomCode(8);
			}
			$this->setUserTemp($blogid, $userkey, $remoteaddr, $logDate);
		}
		$timeout = time() + (7 * 24 * 60 * 60); // 7days
		$path = preg_replace('#^[^/]+//[^/]+(.+)$#', '$1', $blog->getURL());
		setcookie('NP_AccessAnalyze_userkey', $userkey, $timeout, $path);
		
		// siteview(+hourly) count
		$this->setSiteCount($blogid, $logDate, $userview, 1, 0);
		
		// Referer check
		$referer = serverVar('HTTP_REFERER');
		if ($referer !== FALSE) {
			if (stripos($referer, $CONF['IndexURL']) === FALSE) {
				$s_info = $this->getSearchInfo($referer);
				if ($s_info !== FALSE && $s_info['engine']) {
					// search count
					$this->setSearchCount($blogid, $logDate, $s_info);
				}
			} elseif ($type == 'search') {
				// search count
				$s_info = array('engine' => '<search>', 'words' => $query);
				$this->setSearchCount($blogid, $logDate, $s_info);
			}
		}
		
		// Itemview check
		if ($type == 'item') {
			// itemview count
			$this->setItemCount($blogid, $logDate, $itemid);
			
			if (stripos($referer, $CONF['IndexURL']) === FALSE) {
				// referer count
				$this->setRefererCount($blogid, $logDate, $itemid, $referer);
			}
		}
	}
	
	/* get AgentType */
	function getAgentType() {
		/* The order of high priority */
		$enginelist 	= explode(",", "Gecko,WebKit,Opera,Trident,KHTML");
		$blowserlist 	= explode(",", "Firefox,Chrome,rv,MSIE,Safari,Opera,Googlebot,Yahoo!,Y!J,bingbot,Baiduspider,WBSearchBot");
		$oslist 		= explode(",", "Windows NT,Windows,Mac OS,Macintosh,PowerPC,Ubuntu,FreeBSD,Linux");
		
		$ret = array('engine' => '', 'browser' => '', 'os' => '');
		
		/* UserAgent analysis */
		preg_match_all("/\s?([^\s\(\)]+)((?:\s?\([^\)]+\))*)/", serverVar('HTTP_USER_AGENT'), $agent, PREG_PATTERN_ORDER);
		
		/* Token search */
		/* engine */
		$ret['engine'] = $this->inArraySearch($enginelist, $agent[1]);
		/* blowser */
		$ret['browser'] = $this->inArraySearch($blowserlist, $agent[1]);
		$bchech = array($ret['browser']);
		foreach ($agent[1] as $item) {
			if (stripos($item, 'Mozilla') === FALSE && $item != $ret['engine'] && $item != $ret['browser']) $bchech[] = $item;
		}
		unset($item);
		$ret['browser'] = $this->inArraySearch($blowserlist, $bchech);
		
		/* Comment search */
		$agent_sub = array();
		for ($i = 0; $i < count($agent[2]); $i++) {
			preg_match_all("/([^\(\);\s][^;\)]*)/", $agent[2][$i], $comments, PREG_PATTERN_ORDER);
			$agent_sub = array_merge($agent_sub, $comments[1]);
		}
		/* engine */
		if (!$ret['engine']) $ret['engine'] = $this->inArraySearch($enginelist, $agent_sub);
		/* blowser */
		if (!$ret['browser']) $ret['browser'] = $this->inArraySearch($blowserlist, $agent_sub);
		/* os */
		if (!$ret['os']) $ret['os'] = $this->inArraySearch($oslist, $agent_sub);
		
		foreach ($ret as &$item) {
			if (!$item) $item = 'Other';
		}
		unset($item);
		
		return $ret;
	}
	
	/* get searchengine and searchwords */
	function getSearchInfo($url) {
		/* engine_name/host_addresss/query_param/encode_param/default_encode */
		$slist = array(
			explode("/", "google/www.google.co.jp/q//UTF-8"),
			explode("/", "yahoo/search.yahoo.co.jp/p/ei/UTF-8"),
			explode("/", "bing/www.bing.com/q//UTF-8"),
			explode("/", "goo/search.goo.ne.jp/MT/IE/UTF-8"),
			explode("/", "baidu/www.baidu.jp/wd/ie/UTF-8"),
			explode("/", "Ask/jp.ask.com/q//UTF-8"),
			explode("/", "AOL/search.aol.jp/query//UTF-8"),
			explode("/", "au one/search.auone.jp/q/ie/SJIS"));
		
		$ret = array('engine' => '', 'words' => '');
		
		$p_url = parse_url($url);
		if ($p_url === FALSE) return FALSE;
		
		if (array_key_exists('query', $p_url)) {
			$query = $p_url['query'];
		} elseif (array_key_exists('fragment', $p_url)) {
			$query = $p_url['fragment'];
		}
		$queryVals = array();
		if (isset($query)) parse_str($query, $queryVals);
		
		for ($i = 0; $i < count($slist); $i++) {
			if ($p_url['host'] == $slist[$i][1]) {
				$ret['engine'] = $slist[$i][0];
				if (is_array($queryVals) && array_key_exists($slist[$i][2], $queryVals)) {
					$ret['words'] = urldecode($queryVals[$slist[$i][2]]);
					if (strlen($slist[$i][3]) > 0 && array_key_exists($slist[$i][3], $queryVals)) {
						$queryEnc = strtoupper($queryVals[$slist[$i][3]]);
					} else {
						$queryEnc = $slist[$i][4];
					}
					if (!isset($queryEnc)) $queryEnc = 'auto';
					$ret['words'] = mb_convert_encoding($ret['words'], _CHARSET, $queryEnc);
					$ret['words'] = mb_convert_kana($ret['words'], "s", _CHARSET);
				} else {
					$ret['words'] = '(unknown)';
				}
				break;
			}
		}
		
		return $ret;
	}
	
	/*-------------------------------------------
	  DataAccess Functions
	-------------------------------------------*/
	/* get UserTemp tabledata */
	function checkUserKey($blogid, $userKey, $ipaddr, $logDate) {
		if ($userKey) {
			$q = sprintf("SELECT userkey FROM %s WHERE blogid=%s AND userkey='%s' AND accessdate='%s'"
				, $this->tablePrefix('UserTemp')
				, intval($blogid)
				, sql_real_escape_string($userKey)
				, sql_real_escape_string($logDate[0]));
		} else {
			$q = sprintf("SELECT userkey FROM %s WHERE blogid=%s AND ipaddr='%s' AND accessdate='%s'"
				, $this->tablePrefix('UserTemp')
				, intval($blogid)
				, sql_real_escape_string($ipaddr)
				, sql_real_escape_string($logDate[0]));
		}
		$result = sql_query($q);
		if (sql_num_rows($result)) {
			return true;
		} else {
			return false;
		}
	}
	
	/* set UserTemp tabledata */
	function setUserTemp($blogid, $userkey, $ipaddr, $logDate) {
		$hostaddr = gethostbyaddr($ipaddr);
		$q = sprintf("UPDATE %s SET ipaddr='%s', hostaddr='%s', accessdate='%s' WHERE blogid=%s AND userkey='%s'"
			, $this->tablePrefix('UserTemp')
			, sql_real_escape_string($ipaddr)
			, sql_real_escape_string($hostaddr)
			, sql_real_escape_string($logDate[0])
			, intval($blogid)
			, sql_real_escape_string($userkey));
		sql_query($q);
		if (sql_affected_rows() == 0) {
			$q = sprintf("INSERT INTO %s (blogid, userkey, ipaddr, hostaddr, accessdate) VALUES (%s, '%s', '%s', '%s', '%s')"
				, $this->tablePrefix('UserTemp')
				, intval($blogid)
				, sql_real_escape_string($userkey)
				, sql_real_escape_string($ipaddr)
				, sql_real_escape_string($hostaddr)
				, sql_real_escape_string($logDate[0]));
			sql_query($q);
		}
	}
	
	/* set SiteCount tabledata */
	function setSiteCount($blogid, $logDate, $userview, $pageview, $rssview) {
		$q = sprintf("UPDATE %s SET userview=userview+%s, pageview=pageview+%s, rssview=rssview+%s WHERE blogid=%s AND period='%s'"
			, $this->tablePrefix('SiteCount')
			, intval($userview)
			, intval($pageview)
			, intval($rssview)
			, intval($blogid)
			, sql_real_escape_string($logDate[0]));
		sql_query($q);
		if (sql_affected_rows() == 0) {
			$q = sprintf("INSERT INTO %s (blogid, period, userview, pageview, rssview) VALUES (%s, '%s', %s, %s, %s)"
				, $this->tablePrefix('SiteCount')
				, intval($blogid)
				, sql_real_escape_string($logDate[0])
				, intval($userview)
				, intval($pageview)
				, intval($rssview));
			sql_query($q);
		}
		if ($pageview > 0) {
			// hourly count
			$q = sprintf("UPDATE %1\$s SET pageview%2\$s=pageview%2\$s+%3\$s WHERE blogid=%4\$s AND period='%5\$s'"
				, $this->tablePrefix('HourlyCount')
				, sql_real_escape_string($logDate[1])
				, intval($pageview)
				, intval($blogid)
				, sql_real_escape_string($logDate[0]));
			sql_query($q);
			if (sql_affected_rows() == 0) {
				$row = Array();
				for ($i = 0; $i < 24; $i++) $row[sprintf("pageview%02d", $i)] = (intval($logDate[1]) == $i) ? sprintf("%s", intval($pageview)) : '0';
				$q = sprintf("INSERT INTO %s (blogid, period, ".implode(',', array_keys($row)).") VALUES (%s, '%s', ".implode(',', array_values($row)).")"
					, $this->tablePrefix('HourlyCount')
					, intval($blogid)
					, sql_real_escape_string($logDate[0]));
				sql_query($q);
			}
		}
	}
	
	/* set AgentCount tabledata */
	function setAgentCount($blogid, $logDate) {
		$agent = $this->getAgentType();
		$q = sprintf("UPDATE %s SET userview=userview+1 WHERE blogid=%s AND period='%s' AND os='%s' AND engine='%s' AND browser='%s'"
			, $this->tablePrefix('AgentCount')
			, intval($blogid)
			, sql_real_escape_string($logDate[0])
			, sql_real_escape_string($agent['os'])
			, sql_real_escape_string($agent['engine'])
			, sql_real_escape_string($agent['browser']));
		sql_query($q);
		if (sql_affected_rows() == 0) {
			$q = sprintf("INSERT INTO %s (blogid, period, os, engine, browser, userview) VALUES (%s, '%s', '%s', '%s', '%s', 1)"
				, $this->tablePrefix('AgentCount')
				, intval($blogid)
				, sql_real_escape_string($logDate[0])
				, sql_real_escape_string($agent['os'])
				, sql_real_escape_string($agent['engine'])
				, sql_real_escape_string($agent['browser']));
			sql_query($q);
		}
	}
	
	/* set SearchCount tabledata */
	function setSearchCount($blogid, $logDate, $searchInfo) {
		$searchInfo['words'] = trim($searchInfo['words']);
		$searchInfo['words'] = preg_replace("/([[:space:]]{2,})/", ' ', $searchInfo['words']);
		
		$q = sprintf("UPDATE %s SET pageview=pageview+1 WHERE blogid=%s AND period='%s' AND source='%s' AND searchword='%s'"
			, $this->tablePrefix('SearchCount')
			, intval($blogid)
			, sql_real_escape_string($logDate[0])
			, sql_real_escape_string($searchInfo['engine'])
			, sql_real_escape_string($searchInfo['words']));
		sql_query($q);
		if (sql_affected_rows() == 0) {
			$q = sprintf("INSERT INTO %s (blogid, period, source, searchword, pageview) VALUES (%s, '%s', '%s', '%s', 1)"
				, $this->tablePrefix('SearchCount')
				, intval($blogid)
				, sql_real_escape_string($logDate[0])
				, sql_real_escape_string($searchInfo['engine'])
				, sql_real_escape_string($searchInfo['words']));
			sql_query($q);
		}
	}
	
	/* set ItemCount tabledata */
	function setItemCount($blogid, $logDate, $itemid) {
		$q = sprintf("UPDATE %s SET pageview=pageview+1 WHERE blogid=%s AND period='%s' AND itemid=%s"
			, $this->tablePrefix('ItemCount')
			, intval($blogid)
			, sql_real_escape_string($logDate[0])
			, intval($itemid));
		sql_query($q);
		if (sql_affected_rows() == 0) {
			$q = sprintf("INSERT INTO %s (blogid, period, itemid, pageview) VALUES (%s, '%s', %s, 1)"
				, $this->tablePrefix('ItemCount')
				, intval($blogid)
				, sql_real_escape_string($logDate[0])
				, intval($itemid));
			sql_query($q);
		}
	}
	
	/* set RefererCount tabledata */
	function setRefererCount($blogid, $logDate, $itemid, $referer) {
		$p = parse_url($referer);
		if (!$p) return;
		$referer = $p['scheme'].'://'.$p['host'].$p['path'];
		if (!$referer) return;
		
		$q = sprintf("UPDATE %s SET pageview=pageview+1 WHERE blogid=%s AND period='%s' AND itemid=%s AND referer='%s'"
			, $this->tablePrefix('RefererCount')
			, intval($blogid)
			, sql_real_escape_string($logDate[0])
			, intval($itemid)
			, sql_real_escape_string($referer));
		sql_query($q);
		if (sql_affected_rows() == 0) {
			$q = sprintf("INSERT INTO %s (blogid, period, itemid, referer, pageview) VALUES (%s, '%s', %s, '%s', 1)"
				, $this->tablePrefix('RefererCount')
				, intval($blogid)
				, sql_real_escape_string($logDate[0])
				, intval($itemid)
				, sql_real_escape_string($referer));
			sql_query($q);
		}
	}
	
	function deleteBlogCount($blogid) {
		$q = "DELETE FROM %s WHERE blogid=%s";
		sql_query(sprintf($q, $this->tablePrefix('UserTemp'),     intval($blogid)));
		sql_query(sprintf($q, $this->tablePrefix('SiteCount'),    intval($blogid)));
		sql_query(sprintf($q, $this->tablePrefix('HourlyCount'),  intval($blogid)));
		sql_query(sprintf($q, $this->tablePrefix('ItemCount'),    intval($blogid)));
		sql_query(sprintf($q, $this->tablePrefix('RefererCount'), intval($blogid)));
		sql_query(sprintf($q, $this->tablePrefix('SearchCount'),  intval($blogid)));
		sql_query(sprintf($q, $this->tablePrefix('AgentCount'),   intval($blogid)));
	}
	
	function deleteItemCount($itemid) {
		$q = "DELETE FROM %s WHERE itemid=%s";
		sql_query(sprintf($q, $this->tablePrefix('ItemCount'),    intval($itemid)));
		sql_query(sprintf($q, $this->tablePrefix('RefererCount'), intval($itemid)));
	}
	
	function setInitialCount($blogid) {
		sql_query(sprintf("DELETE FROM %s WHERE blogid=%s AND period='0000'"
			, $this->tablePrefix('SiteCount')
			, intval($blogid)));
		sql_query(sprintf("INSERT INTO %s (blogid, period, userview, pageview, rssview) VALUES (%s, '0000', %s, %s, 0)"
			, $this->tablePrefix('SiteCount')
			, intval($blogid)
			, intval($this->getBlogOption($blogid, 'initialUserView'))
			, intval($this->getBlogOption($blogid, 'initialPageView'))));
	}
	
	function createCounter() {
		global $blogid;
		
		$template = $this->getBlogOption($blogid, 'counterTemplate');
		preg_match_all('/%([^%]+)%/', $template, $matches, PREG_PATTERN_ORDER);
		$useCounts = implode(',', $matches[1]);
		
		$retVal = array('total_uv' => 0, 'total_pv' => 0, 'today_uv' => 0, 'today_pv' => 0
			, 'yesterday_uv' => 0, 'yesterday_pv' => 0, 'week_uv' => 0, 'week_pv' => 0);
		if (stripos($useCounts, 'total_') !== FALSE) {
			$q = sprintf("SELECT SUM(userview) AS userview, SUM(pageview) AS pageview FROM %s WHERE blogid=%s"
				, $this->tablePrefix('SiteCount')
				, intval($blogid));
			$result = sql_query($q);
			if (sql_num_rows($result)) {
				while($o = sql_fetch_assoc($result)) {
					$retVal['total_uv'] = intval($o['userview']) ? intval($o['userview']) : 0;
					$retVal['total_pv'] = intval($o['pageview']) ? intval($o['pageview']) : 0;
				}
			} else {
				return $retVal;
			}
		}
		if (stripos($useCounts, 'today_') !== FALSE) {
			$q = sprintf("SELECT SUM(userview) AS userview, SUM(pageview) AS pageview FROM %s WHERE blogid=%s AND period='%s'"
				, $this->tablePrefix('SiteCount')
				, intval($blogid)
				, sql_real_escape_string(date('Ymd')));
			$result = sql_query($q);
			if (sql_num_rows($result)) {
				while($o = sql_fetch_assoc($result)) {
					$retVal['today_uv'] = intval($o['userview']) ? intval($o['userview']) : 0;
					$retVal['today_pv'] = intval($o['pageview']) ? intval($o['pageview']) : 0;
				}
			}
		}
		if (stripos($useCounts, 'yesterday_') !== FALSE) {
			$wdate = new DateTime();
			$wdate->sub(new DateInterval('P1D'));
			$q = sprintf("SELECT SUM(userview) AS userview, SUM(pageview) AS pageview FROM %s WHERE blogid=%s AND period='%s'"
				, $this->tablePrefix('SiteCount')
				, intval($blogid)
				, sql_real_escape_string($wdate->format('Ymd')));
			$result = sql_query($q);
			if (sql_num_rows($result)) {
				while($o = sql_fetch_assoc($result)) {
					$retVal['yesterday_uv'] = intval($o['userview']) ? intval($o['userview']) : 0;
					$retVal['yesterday_pv'] = intval($o['pageview']) ? intval($o['pageview']) : 0;
				}
			}
		}
		if (stripos($useCounts, 'week_') !== FALSE) {
			$wdate = new DateTime();
			while ($wdate->format('w') != 0) $wdate->sub(new DateInterval('P1D'));
			$q = sprintf("SELECT SUM(userview) AS userview, SUM(pageview) AS pageview FROM %s WHERE blogid=%s AND period>='%s'"
				, $this->tablePrefix('SiteCount')
				, intval($blogid)
				, sql_real_escape_string($wdate->format('Ymd')));
			$result = sql_query($q);
			if (sql_num_rows($result)) {
				while($o = sql_fetch_assoc($result)) {
					$retVal['week_uv'] = intval($o['userview']) ? intval($o['userview']) : 0;
					$retVal['week_pv'] = intval($o['pageview']) ? intval($o['pageview']) : 0;
				}
			}
		}
		
		return TEMPLATE::fill($template, $retVal);
	}
	
	function createItemRank($span = '1week', $limit = 5, $postDateFormat = 'Y-m-d') {
		global $blogid, $manager;
		
		$template = $this->getBlogOption($blogid, 'itemRankTemplate');
		
		$interval = 1;
		$unit = 'week';
		if (preg_match('/^(\d+)?(\w+)$/', $span, $matches)) {
			$interval = intval($matches[1]) ? intval($matches[1]) : 1;
			$unit = $matches[2];
		}
		if (!is_numeric($limit)) $limit = 5;
		if (!$postDateFormat) $postDateFormat = 'Y-m-d';
		
		$tgDate = new DateTime();
		switch (strtolower($unit)) {
			case 'total': $qPeriod = ''; break;
			case 'month': case 'months':
				$tgDate->sub(new DateInterval('P'.$interval.'M'));
				$qPeriod = sprintf("AND period>'%s'", $tgDate->format("Ymd"));
				break;
			case 'day': case 'days':
				$tgDate->sub(new DateInterval('P'.$interval.'D'));
				$qPeriod = sprintf("AND period>'%s'", $tgDate->format("Ymd"));
				break;
			default: // week
				$interval *= 7;
				$tgDate->sub(new DateInterval('P'.$interval.'D'));
				$qPeriod = sprintf("AND period>'%s'", $tgDate->format("Ymd"));
				break;
		}
		$q = sprintf("SELECT itemid, SUM(pageview) AS pageview FROM %s"
			." WHERE blogid=%s ".$qPeriod." GROUP BY itemid ORDER BY pageview DESC, itemid DESC LIMIT %s"
			, $this->tablePrefix('ItemCount')
			, intval($blogid)
			, intval($limit));
		$result = sql_query($q);
		
		$rank = 1;
		$data = array();
		if (sql_num_rows($result)) {
			while($o = sql_fetch_assoc($result)) {
				$item =& $manager->getItem($o['itemid'], TRUE, TRUE);
				$comments = new COMMENTS($o['itemid']);
				$data[] = array('rank' => $rank
					, 'title' => $item['title']
					, 'postdate' => date($postDateFormat, $item['timestamp'])
					, 'itemlink' => createItemLink(intval($o['itemid']))
					, 'comments' => $comments->amountComments()
					, 'pageview' => $o['pageview']
					);
				$rank++;
			}
		}
		
		$ret = '';
		foreach ($data as $values) {
			$ret .= TEMPLATE::fill($template, $values);
		}
		return $ret;
	}
}