Files
plugins/Stat/Plugin.php
chorblack e75f275ef4
Some checks failed
定时更新GitHub源插件 / 自动更新GitHub插件 (push) Has been cancelled
Initial commit
2026-03-07 11:19:25 +08:00

202 lines
6.5 KiB
PHP

<?php
if (!defined('__TYPECHO_ROOT_DIR__')) exit;
/**
* 页面浏览次数统计插件 【<a href="https://github.com/typecho-fans/plugins" target="_blank">TF</a>社区维护版】
*
* @package Stat
* @author 羽中, Jozhn, Hanny
* @version 1.0.4
* @dependence 17.10.30-*
* @link https://github.com/typecho-fans/plugins/tree/master/Stat
*
* version 1.0.4 at 2020-07-08
* 增加计数输出和忽略重复访问功能
* 增加排行输出可指定分类ID与类型
*
* version 1.0.3 at 2018-08-24
* 修复PDO下数据表检测失败的错误
*
* 历史版本
* version 1.0.2 at 2010-07-03
* 终于支持前台调用了
* 接口支持Typecho 0.8的计数
* 增加SQLite的支持
* version 1.0.1 at 2010-01-02
* 修改安装出错处理
* 修改安装时默认值错误
* version 1.0.0 at 2009-12-12
* 实现浏览次数统计的基本功能
*/
class Stat_Plugin implements Typecho_Plugin_Interface
{
/**
* 激活插件方法,如果激活失败,直接抛出异常
*
* @access public
* @return void
* @throws Typecho_Plugin_Exception
*/
public static function activate()
{
$info = Stat_Plugin::sqlInstall();
Typecho_Plugin::factory('Widget_Archive')->singleHandle = array('Stat_Plugin', 'singleHandle');
Typecho_Plugin::factory('Widget_Archive')->select = array('Stat_Plugin', 'selectHandle');
/* 模版调用钩子 */
Typecho_Plugin::factory('Widget_Archive')->callStat = array('Stat_Plugin', 'outputStat');
/* 输出排行支持4种参数如: <?php $this->rank(
'源码含{link}{title}',
'类型如post/page/attachment',
'分类或标签mid用逗号隔开',
条目数
); ?> */
Typecho_Plugin::factory('Widget_Archive')->callRank = array('Stat_Plugin', 'outputRank');
return _t($info);
}
//SQL创建
public static function sqlInstall()
{
$db = Typecho_Db::get();
$type = explode('_', $db->getAdapterName());
$type = array_pop($type);
$prefix = $db->getPrefix();
try {
$select = $db->select('table.contents.views')->from('table.contents');
$db->query($select, Typecho_Db::READ);
return '检测到统计字段,插件启用成功';
} catch (Typecho_Db_Exception $e) {
$code = $e->getCode();
if(('Mysql' == $type && ('42S22'==$code || 1054 == $code)) ||
('SQLite' == $type && ('HY000' == $code || 1 == $code))) {
try {
if ('Mysql' == $type) {
$db->query("ALTER TABLE `".$prefix."contents` ADD `views` INT( 10 ) NOT NULL DEFAULT '0' COMMENT '页面浏览次数';");
} else if ('SQLite' == $type) {
$db->query("ALTER TABLE `".$prefix."contents` ADD `views` INT( 10 ) NOT NULL DEFAULT '0'");
} else {
throw new Typecho_Plugin_Exception('不支持的数据库类型:'.$type);
}
return '建立统计字段,插件启用成功';
} catch (Typecho_Db_Exception $e) {
$code = $e->getCode();
if(('Mysql' == $type && ('42S21'==$code || 1060 == $code)) ) {
return '统计字段已经存在,插件启用成功';
}
throw new Typecho_Plugin_Exception('统计插件启用失败。错误号:'.$code);
}
}
throw new Typecho_Plugin_Exception('数据表检测失败,统计插件启用失败。错误号:'.$code);
}
}
/**
* 禁用插件方法,如果禁用失败,直接抛出异常
*
* @static
* @access public
* @return void
* @throws Typecho_Plugin_Exception
*/
public static function deactivate(){}
/**
* 获取插件配置面板
*
* @access public
* @param Typecho_Widget_Helper_Form $form 配置面板
* @return void
*/
public static function config(Typecho_Widget_Helper_Form $form){}
/**
* 个人用户的配置面板
*
* @access public
* @param Typecho_Widget_Helper_Form $form
* @return void
*/
public static function personalConfig(Typecho_Widget_Helper_Form $form){}
/**
* 插件实现方法
*
* @access public
* @return void
*/
public static function outputStat($widget)
{
$db = Typecho_Db::get();
$row = $db->fetchRow($db->select('views')->from('table.contents')->where('cid = ?', $widget->cid));
echo $row['views'];
}
public static function viewStat($cid)
{
$name = '__StatViews';
$cids = Json::decode(Typecho_Cookie::get($name), true);
if (!empty($cids) && in_array($cid, $cids)) {
return;
} else {
if (!$cids) $cids = array();
array_push($cids, $cid);
Typecho_Cookie::set($name, Json::encode($cids), time()+60*60); //默认60分钟可自行修改
$db = Typecho_Db::get();
$prefix = $db->getPrefix();
$sql = "UPDATE `".$prefix."contents` SET `views` = `views` + 1 WHERE `cid` = ".intval($cid).";";
$db->query($sql);
}
}
public static function selectHandle($archive)
{
$db = Typecho_Db::get();
$options = Typecho_Widget::widget('Widget_Options');
return $db->select('*')->from('table.contents')->where('table.contents.status = ?', 'publish')
->where('table.contents.created < ?', $options->gmtTime);
}
public static function singleHandle($select, $archive)
{
Stat_Plugin::viewStat($select->stack[0]['cid']);
}
public static function outputRank($widget, array $params)
{
$db = Typecho_Db::get();
$items = $db->fetchAll($db->select('table.metas.mid')->from('table.metas')
->where('table.metas.type = ?', 'category'));
foreach ($items as $item) {
$all[] = $item['mid'];
}
$format = !empty($params[0]) && is_string($params[0]) ? $params[0] : '<li><a href="{link}">{title}</a></li>';
$type = !empty($params[1]) && is_string($params[1]) ? $params[1] : 'post';
$category = !empty($params[2]) && is_string($params[2]) ? $params[2] : 'ALL';
$limit = !empty($params[3]) && is_numeric($params[3]) ? $params[3] : 10;
if ($type == 'post') {
$select = $db->select()->from('table.contents')
->join('table.relationships', 'table.relationships.cid = table.contents.cid',Typecho_Db::INNER_JOIN)
->where('table.contents.status = ?', 'publish')
->where('table.relationships.mid in ('.($category=='ALL' ? implode(',', $all) : $category).')')
->order('views', Typecho_Db::SORT_DESC)
->limit($limit);
} else {
$select = $db->select()->from('table.contents')
->where('table.contents.status = ?', 'publish')
->where('table.contents.type = ?', ''.$type.'')
->order('views', Typecho_Db::SORT_DESC)
->limit($limit);
}
$posts = $db->fetchAll($select);
foreach ($posts as $post) {
$value = Typecho_Widget::widget('Widget_Abstract_Contents')->push($post);
echo str_replace(array('{link}','{title}'), array($value['permalink'], $value['title']), $format);
}
}
}