4 by yu (http://nucleus.datoka.jp/)
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License
8 as published by the Free Software Foundation; either version 2
9 of the License, or (at your option) any later version.
10 (see nucleus/documentation/index.html#license for more info)
15 <%media(file path|link text)%> //auto count mode
16 <%media(file path|link text|linkcnt=KEYWORD)%> //set original keyword
17 <%LinkCounter(link,KEYWORD,URL,linktext,target prop,title prop)%>
18 <%LinkCounter(total,KEYWORD)%>
21 <%LinkCounter(link,KEYWORD,URL,linktext,target prop,title prop)%>
22 <%LinkCounter(total,KEYWORD)%>
27 2008/05/14 Ver 0.4 : [Chg] Unsupport <a linkcnt="*keyword*"> and <#linkcnt_total(*keyword*)#>.
28 [Add] Support <%LinkCounter()%> in item.
29 [Add] Option "Keyword of feeds skin name" (exkey).
30 2006/11/21 Ver 0.32 : [Fix] Security fix.
31 2006/09/30 Ver 0.31 : [Fix] Security fix.
32 2004/08/12 Ver 0.3 : [Chg] Shorten linkcountURL, and [Add] Auto count mode for media tag.
33 2004/04/14 Ver 0.2 : [Add] skin description, and total count.
34 2004/02/16 Ver 0.1 : First release.
37 // plugin needs to work on Nucleus versions <=2.0 as well
38 if (!function_exists('sql_table')) {
39 function sql_table($name) {
40 return 'nucleus_' . $name;
44 // quote variable to make safe
45 if(!function_exists('quote_smart')) {
48 class NP_LinkCounter extends NucleusPlugin {
49 function getName() { return 'Link Counter'; }
50 function getAuthor() { return 'yu'; }
51 function getURL() { return 'http://works.datoka.jp/'; }
52 function getVersion() { return '0.4'; }
53 function getMinNucleusVersion() { return 200; }
54 function getTableList() { return array( sql_table('plug_linkcounter') ); }
55 function getEventList() { return array( 'PreItem' ); }
56 function supportsFeature($what) {
58 case 'SqlTablePrefix':
65 function getDescription() {
66 return 'Link counter. [USAGE] mediavar - <%media(file|text|linkcnt=keyword)%> '.
67 'or itemvar - <%LinkCounter(link,url,linktext,target,title)%> '.
68 'or <%LinkCounter(total,keyword)%>';
73 sql_query ("CREATE TABLE IF NOT EXISTS ". sql_table('plug_linkcounter') ." (
74 lkey VARCHAR(64) NOT NULL,
75 cnt INT UNSIGNED NOT NULL DEFAULT 1,
76 url VARCHAR(255) NOT NULL DEFAULT '',
77 primary key (lkey))");
79 $this->createOption('tpl_cnt', 'Counter Template.', 'text', '[$cnt$word]');
80 $this->createOption('tpl_word1', 'Unit word for template (singlar form).', 'text', 'click');
81 $this->createOption('tpl_word2', 'Unit word for template (plural form).', 'text', 'clicks');
82 $this->createOption('flg_auto', 'Auto count mode for media tag (no need to add "linkcnt" property).', 'yesno', 'yes');
83 $this->createOption('exkey', 'Keyword of feeds skin name (invalidate showing counter for XML syndication).' ,'text','feeds');
84 $this->createOption('flg_erase', 'Erase data on uninstall.', 'yesno', 'no');
87 function unInstall() {
88 if ($this->getOption(flg_erase) == 'yes') {
89 sql_query ('DROP TABLE '. sql_table('plug_linkcounter') );
95 $this->tpl_cnt = $this->getOption('tpl_cnt');
96 $this->tpl_word1 = $this->getOption('tpl_word1');
97 $this->tpl_word2 = $this->getOption('tpl_word2');
98 $this->flg_auto = ($this->getOption('flg_auto') == 'yes');
99 $this->exkey = $this->getOption('exkey');
101 $query = "SHOW TABLES LIKE '". sql_table('plug_linkcounter') ."'";
102 $table = sql_query($query);
103 if (mysql_num_rows($table) > 0){
104 $query = "SELECT * FROM ". sql_table('plug_linkcounter');
105 $res = sql_query($query);
106 while ($link = mysql_fetch_object($res)) { //copy all data
107 $this->link[$link->lkey]['cnt'] = intval($link->cnt);
108 $this->link[$link->lkey]['url'] = stripslashes($link->url);
114 function doSkinVar($skinType, $mode='total', $key='', $url='', $linktext='', $target='', $title='') {
117 if ($mode == 'link' and $key) {
118 $cnt = $this->link[$key]['cnt'];
120 $retlink = $this->_make_link($key, $url, $linktext, $target, $title);
121 $retcnt = $this->_make_counter($cnt);
123 print $retlink.$retcnt;
125 else if ($mode == 'total' and $key) {
126 $cnt = $this->_get_total($key);
127 $retcnt = $this->_make_counter($cnt);
132 function doItemVar(&$item, $mode='total', $key='', $url='', $linktext='', $target='', $title='') {
133 $this->doSkinVar('', $mode, $key, $url, $linktext, $target, $title);
136 function doTemplateVar(&$item, $mode='total', $key='', $url='', $linktext='', $target='', $title='') {
137 $this->doSkinVar('', $mode, $key, $url, $linktext, $target, $title);
141 function event_PreItem($data) {
143 $tgt = '/<%media\((.+?)\)%>/';
145 // convert to linkcounter
146 $obj = &$data["item"];
147 $this->authorid = $obj->authorid;
148 $obj->body = preg_replace_callback($tgt, array(&$this, 'makelink_callback'), $obj->body);
149 $obj->more = preg_replace_callback($tgt, array(&$this, 'makelink_callback'), $obj->more);
153 function doAction($type) {
158 $key = urldecode(getVar('k'));
159 $url = getVar('url');
161 if ($this->link[$key]['cnt']) {
162 $query = sprintf("UPDATE %s SET cnt=%d WHERE lkey=%s",
163 sql_table('plug_linkcounter'),
164 $this->link[$key]['cnt'] +1,
165 $this->quote_smart($key) );
166 if (!$url) $url = $this->link[$key]['url']; // get url from db (that was first recorded)
169 if (!$url) $url = serverVar('HTTP_REFERER');
170 $url = preg_replace('|[^a-z0-9-~+_.?#=&;,/:@%]|i', '', $url);
171 $query = sprintf("INSERT INTO %s SET lkey=%s, cnt=1, url=%s",
172 sql_table('plug_linkcounter'),
173 $this->quote_smart($key),
174 $this->quote_smart($url) );
181 redirect( serverVar('HTTP_REFERER') );
187 function makelink_callback($m) {
192 if ($mcnt == 2) { // media var
193 $mvar = explode('|', $m[1]);
194 if (!$mvar[2]) { // no extra property
195 if (!$this->flg_auto) return $m[0]; // return as it is
196 list($key, $tgt, $tit, $linktext) = array($mvar[0], '', '', $mvar[1]);
199 $lc = split('linkcnt=', $mvar[2]);
200 if (!$lc[1]) { // no linkcnt property
201 return $m[0]; // return as it is
203 list($key, $tgt, $tit, $linktext) = array($lc[1], '', '', $mvar[1]);
206 if ( strstr($mvar[0], '/') ) $memberdir = '';
207 else $memberdir = $this->authorid . '/';
208 $url = $CONF['MediaURL'] . $memberdir . $mvar[0];
210 else return $m[0]; //invalid match. return as it is
212 $retlink = $this->_make_link($key, $url, $linktext, $tgt, $tit);
213 $cnt = $this->link[$key]['cnt'];
214 $retcnt = $this->_make_counter($cnt);
215 return $retlink . $retcnt;
220 function _make_link($key, $url, $linktext, $tgt, $tit) {
223 $base = $CONF['ActionURL'] .'?action=plugin&name=LinkCounter&type=c';
226 $saved_url = $this->link[$key]['url'];
227 if ($saved_url and $url == $saved_url)
228 $url = ''; // it omits url parameter to make short url
230 $key = urlencode($key);
232 if ($url) $urlstr = "&url=$url";
233 if ($tgt) $tgtstr = " target='$tgt'";
234 if ($tit) $titstr = " title='{$tit}'";
235 $retlink = "<a href='{$base}&k={$key}{$urlstr}'{$tgtstr}{$titstr}>$linktext</a>";
240 function _make_counter($cnt) {
241 global $currentSkinName;
243 if (strpos($currentSkinName, $this->exkey) !== false) return '';
245 $tpl = $this->tpl_cnt;
246 if ($cnt <= 1) $word = $this->tpl_word1;
247 else $word = $this->tpl_word2;
248 $ary_target = array('$cnt', '$word');
249 $ary_replace = array( (int)$cnt, $word);
250 $retcnt = str_replace($ary_target, $ary_replace, $tpl);
255 function _get_total($key) {
256 $key = $this->quote_smart('%'.$key.'%');
259 $query = "SELECT SUM(cnt) AS cnt FROM ". sql_table('plug_linkcounter');
260 $query.= " WHERE lkey LIKE $key";
261 $res = sql_query($query);
262 $rcnt = mysql_fetch_object($res);
268 function quote_smart($value) {
269 if (get_magic_quotes_gpc()) $value = stripslashes($value);
270 $value = mysql_real_escape_string($value);
271 if (! is_numeric($value)) $value = "'". $value ."'";