OSDN Git Service

Unsupport <a linkcnt="*keyword*"> and <#linkcnt_total(*keyword*)#>.
[nucleus-jp/nucleus-plugins.git] / trunk / NP_LinkCounter / NP_LinkCounter.php
1 <?php 
2 /*
3         NP_LinkCounter
4         by yu (http://nucleus.datoka.jp/)
5
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)
11         
12         USAGE
13         -----
14         In item:
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)%>
19         
20         Others:
21         <%LinkCounter(link,KEYWORD,URL,linktext,target prop,title prop)%>
22         <%LinkCounter(total,KEYWORD)%>
23         
24         
25         HISTORY
26         -------
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. 
35 */
36
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;
41         }
42 }
43
44 // quote variable to make safe
45 if(!function_exists('quote_smart')) {
46 }
47
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) {
57                 switch($what) {
58                         case 'SqlTablePrefix':
59                                 return 1;
60                         default:
61                                 return 0;
62                 }
63         }
64
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)%>';
69         } 
70
71
72         function install(){ 
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))");
78                 
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');
85         } 
86         
87         function unInstall() { 
88                 if ($this->getOption(flg_erase) == 'yes') {
89                         sql_query ('DROP TABLE '. sql_table('plug_linkcounter') );
90                 }
91         } 
92         
93         
94         function init() {
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');
100                 
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);
109                         }
110                 }
111         }
112         
113         
114         function doSkinVar($skinType, $mode='total', $key='', $url='', $linktext='', $target='', $title='') {
115                 global $CONF;
116                 
117                 if ($mode == 'link' and $key) {
118                         $cnt = $this->link[$key]['cnt'];
119                         
120                         $retlink = $this->_make_link($key, $url, $linktext, $target, $title);
121                         $retcnt  = $this->_make_counter($cnt);
122                         
123                         print $retlink.$retcnt;
124                 }
125                 else if ($mode == 'total' and $key) {
126                         $cnt = $this->_get_total($key);
127                         $retcnt  = $this->_make_counter($cnt);
128                         print $retcnt;
129                 }
130         }
131         
132         function doItemVar(&$item, $mode='total', $key='', $url='', $linktext='', $target='', $title='') {
133                 $this->doSkinVar('', $mode, $key, $url, $linktext, $target, $title);
134         }
135         
136         function doTemplateVar(&$item, $mode='total', $key='', $url='', $linktext='', $target='', $title='') {
137                 $this->doSkinVar('', $mode, $key, $url, $linktext, $target, $title);
138         }
139         
140         
141         function event_PreItem($data) { 
142                 // prepare
143                 $tgt  = '/<%media\((.+?)\)%>/';
144                 
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); 
150         } 
151         
152         
153         function doAction($type) {
154                 global $CONF;
155                 
156                 switch($type) {
157                         case 'c':
158                                 $key = urldecode(getVar('k'));
159                                 $url = getVar('url');
160                                 
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)
167                                 }
168                                 else {
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) );
175                                 }
176                                 sql_query($query);
177                                 
178                                 redirect($url);
179                                 break;
180                         default:
181                                 redirect( serverVar('HTTP_REFERER') );
182                                 break;
183                 }
184         }
185         
186         
187         function makelink_callback($m) {
188                 global $CONF;
189         
190                 $mcnt = count($m);
191                 
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]);
197                         }
198                         else {
199                                 $lc = split('linkcnt=', $mvar[2]);
200                                 if (!$lc[1]) { // no linkcnt property
201                                         return $m[0]; // return as it is
202                                 }
203                                 list($key, $tgt, $tit, $linktext) = array($lc[1], '', '', $mvar[1]);
204                         }
205                         
206                         if ( strstr($mvar[0], '/') ) $memberdir = '';
207                         else $memberdir = $this->authorid . '/';
208                         $url = $CONF['MediaURL'] . $memberdir . $mvar[0];
209                 }
210                 else return $m[0]; //invalid match. return as it is
211                 
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;
216         }
217         
218         
219         //helper function
220         function _make_link($key, $url, $linktext, $tgt, $tit) {
221                 global $CONF;
222                 
223                 $base = $CONF['ActionURL'] .'?action=plugin&amp;name=LinkCounter&amp;type=c';
224                 
225                 //compare urls
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
229                 
230                 $key = urlencode($key);
231                 
232                 if ($url) $urlstr = "&amp;url=$url";
233                 if ($tgt) $tgtstr = " target='$tgt'";
234                 if ($tit) $titstr = " title='{$tit}'";
235                 $retlink = "<a href='{$base}&amp;k={$key}{$urlstr}'{$tgtstr}{$titstr}>$linktext</a>";
236                 
237                 return $retlink;
238         }
239         
240         function _make_counter($cnt) {
241                 global $currentSkinName;
242                 
243                 if (strpos($currentSkinName, $this->exkey) !== false) return '';
244                 
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);
251                 
252                 return $retcnt;
253         }
254
255         function _get_total($key) {
256                 $key = $this->quote_smart('%'.$key.'%');
257                 
258                 // total count
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);
263                 $total = $rcnt->cnt;
264                 
265                 return $total;
266         }
267
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 ."'";
272                 
273                 return $value;
274         }
275 }
276 ?>