2 // PukiWiki - Yet another WikiWikiWeb clone
5 // 2002-2019 PukiWiki Development Team
6 // 2002 Y.MASUI GPL2 http://masui.net/pukiwiki/ masui@masui.net
9 // Counter plugin (per page)
11 // Counter file's suffix
12 define('PLUGIN_COUNTER_SUFFIX', '.count');
13 // Use Database (1) or not (0)
14 define('PLUGIN_COUNTER_USE_DB', 0);
15 // Database Connection setting
16 define('PLUGIN_COUNTER_DB_CONNECT_STRING', 'sqlite:counter/counter.db');
17 define('PLUGIN_COUNTER_DB_USERNAME', '');
18 define('PLUGIN_COUNTER_DB_PASSWORD', '');
19 global $plugin_counter_db_options;
20 $plugin_counter_db_options = null;
22 // $plugin_counter_db_options = array(PDO::MYSQL_ATTR_INIT_COMMAND =>
23 // "SET NAMES utf8mb4 COLLATE utf8mb4_bin");
25 define('PLUGIN_COUNTER_DB_TABLE_NAME_PREFIX', '');
27 if (PLUGIN_COUNTER_USE_DB) {
28 ini_set('default_socket_timeout', 2);
32 function plugin_counter_inline()
36 // BugTrack2/106: Only variables can be passed by reference from PHP 5.0.5
37 $args = func_get_args(); // with array_shift()
39 $arg = strtolower(array_shift($args));
41 case '' : $arg = 'total'; /*FALLTHROUGH*/
42 case 'total': /*FALLTHROUGH*/
43 case 'today': /*FALLTHROUGH*/
45 $counter = plugin_counter_get_count($vars['page']);
46 return $counter[$arg];
48 return '&counter([total|today|yesterday]);';
53 function plugin_counter_convert()
57 $counter = plugin_counter_get_count($vars['page']);
60 Counter: {$counter['total']},
61 today: {$counter['today']},
62 yesterday: {$counter['yesterday']}
68 function plugin_counter_get_count($page)
70 global $vars, $plugin_counter_db_options;
71 static $counters = array();
73 $page_counter_t = PLUGIN_COUNTER_DB_TABLE_NAME_PREFIX . 'page_counter';
75 if (! isset($default))
78 'date' => get_date('Y/m/d'),
83 if (! is_page($page)) return $default;
84 if (isset($counters[$page])) return $counters[$page];
87 $counters[$page] = $default;
89 $c = & $counters[$page];
91 if (PLUGIN_COUNTER_USE_DB) {
92 if (SOURCE_ENCODING !== 'UTF-8') {
93 die('counter.inc.php: Database counter is only available in UTF-8 mode');
97 $pdo = new PDO(PLUGIN_COUNTER_DB_CONNECT_STRING,
98 PLUGIN_COUNTER_DB_USERNAME, PLUGIN_COUNTER_DB_PASSWORD,
99 $plugin_counter_db_options);
100 $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
101 $pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
102 $pdo->setAttribute(PDO::ATTR_TIMEOUT, 5);
103 $stmt = $pdo->prepare(
104 "SELECT total, update_date,
105 today_viewcount, yesterday_viewcount, remote_addr
109 $stmt->execute(array($page));
114 $c['ip'] = $r['remote_addr'];
115 $c['date'] = $r['update_date'];
116 $c['yesterday'] = intval($r['yesterday_viewcount']);
117 $c['today'] = intval($r['today_viewcount']);
118 $c['total'] = intval($r['total']);
119 $stmt->closeCursor();
121 } catch (Exception $e) {
123 $db_error = '(DBError)';
125 'total' => $db_error,
127 'today' => $db_error,
128 'yesterday' => $db_error,
133 $file = COUNTER_DIR . encode($page) . PLUGIN_COUNTER_SUFFIX;
134 pkwk_touch_file($file);
135 $fp = fopen($file, 'r+')
136 or die('counter.inc.php: Cannot open COUNTER_DIR/' . basename($file));
137 set_file_buffer($fp, 0);
142 foreach (array_keys($default) as $key) {
144 $c[$key] = rtrim(fgets($fp, 256));
145 if (feof($fp)) break;
150 $remote_addr = $_SERVER['REMOTE_ADDR'];
152 if ($c['date'] != $default['date']) {
154 $is_yesterday = ($c['date'] == get_date('Y/m/d', UTIME - 24 * 60 * 60));
155 $c[$page]['ip'] = $remote_addr;
156 $c['date'] = $default['date'];
157 $c['yesterday'] = $is_yesterday ? $c['today'] : 0;
161 } else if ($c['ip'] != $remote_addr) {
164 $c['ip'] = $remote_addr;
170 if (PLUGIN_COUNTER_USE_DB) {
171 if ($modify && $vars['cmd'] == 'read') {
175 $add_stmt = $pdo->prepare(
176 "INSERT INTO $page_counter_t
177 (page_name, total, update_date, today_viewcount,
178 yesterday_viewcount, remote_addr)
179 VALUES (?, ?, ?, ?, ?, ?)"
181 $r_add = $add_stmt->execute(array($page, $c['total'],
182 $c['date'], $c['today'], $c['yesterday'], $c['ip']));
183 } else if ($count_up) {
184 // Update on counting up 'total'
185 $upd_stmt = $pdo->prepare(
186 "UPDATE $page_counter_t
187 SET total = total + 1,
190 yesterday_viewcount = ?,
194 $r_upd = $upd_stmt->execute(array($c['date'],
195 $c['today'], $c['yesterday'], $c['ip'], $page));
197 } catch (PDOException $e) {
198 foreach (array_keys($c) as $key) {
199 $c[$key] .= '(DBError)';
205 if ($modify && $vars['cmd'] == 'read') {
208 foreach (array_keys($default) as $key)
209 fputs($fp, $c[$key] . "\n");
218 function plugin_counter_get_popular_list($today, $except, $max) {
219 if (PLUGIN_COUNTER_USE_DB === 0) {
220 return plugin_counter_get_popular_list_file($today, $except, $max);
222 return plugin_counter_get_popular_list_db($today, $except, $max);
226 function plugin_counter_get_popular_list_file($today, $except, $max) {
229 $except_quote = str_replace('#', '\#', $except);
230 foreach (get_existpages(COUNTER_DIR, '.count') as $file=>$page) {
231 if (($except != '' && preg_match("#$except_quote#", $page)) ||
232 $page == $whatsnew || check_non_list($page) ||
236 $array = file(COUNTER_DIR . $file);
237 $count = rtrim($array[0]);
238 $date = rtrim($array[1]);
239 $today_count = rtrim($array[2]);
242 // $pageが数値に見える(たとえばencode('BBS')=424253)とき、
243 // array_splice()によってキー値が変更されてしまうのを防ぐ
245 if ($today == $date) $counters['_' . $page] = $today_count;
247 $counters['_' . $page] = $count;
251 asort($counters, SORT_NUMERIC);
253 // BugTrack2/106: Only variables can be passed by reference from PHP 5.0.5
254 $counters = array_reverse($counters, TRUE); // with array_splice()
255 $counters = array_splice($counters, 0, $max);
259 function plugin_counter_get_popular_list_db($today, $except, $max) {
261 $page_counter_t = PLUGIN_COUNTER_DB_TABLE_NAME_PREFIX . 'page_counter';
263 $order_by_c = 'today_viewcount';
265 $order_by_c = 'total';
269 $pdo = new PDO(PLUGIN_COUNTER_DB_CONNECT_STRING,
270 PLUGIN_COUNTER_DB_USERNAME, PLUGIN_COUNTER_DB_PASSWORD,
271 $plugin_counter_db_options);
272 $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
273 $pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
274 $pdo->setAttribute(PDO::ATTR_TIMEOUT, 5);
276 $stmt = $pdo->prepare(
277 "SELECT page_name, total, update_date,
278 today_viewcount, yesterday_viewcount
280 WHERE update_date = ?
281 ORDER BY $order_by_c DESC
285 $stmt = $pdo->prepare(
286 "SELECT page_name, total, update_date,
287 today_viewcount, yesterday_viewcount
289 ORDER BY $order_by_c DESC
293 $except_quote = str_replace('#', '\#', $except);
296 $stmt->execute(array($today, $limit));
298 $stmt->execute(array($limit));
300 foreach ($stmt as $r) {
301 $page = $r['page_name'];
302 if (($except != '' && preg_match("#$except_quote#", $page)) ||
303 $page == $whatsnew || check_non_list($page) ||
308 $counters['_' . $page] = $r['today_viewcount'];
310 $counters['_' . $page] = $r['total'];
313 $stmt->closeCursor();
314 return array_splice($counters, 0, $max);
315 } catch (Exception $e) {
316 die('counter.inc.php: Error occurred on getting pupular pages');
320 function plugin_counter_page_rename($pages) {
321 global $plugin_counter_db_options;
322 if (PLUGIN_COUNTER_USE_DB !== 0) {
323 $page_counter_t = PLUGIN_COUNTER_DB_TABLE_NAME_PREFIX . 'page_counter';
324 $pdo = new PDO(PLUGIN_COUNTER_DB_CONNECT_STRING,
325 PLUGIN_COUNTER_DB_USERNAME, PLUGIN_COUNTER_DB_PASSWORD,
326 $plugin_counter_db_options);
327 $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
328 $pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
329 $stmt_delete = $pdo->prepare(
330 "DELETE FROM $page_counter_t
333 $stmt_rename = $pdo->prepare(
334 "UPDATE $page_counter_t
338 foreach ($pages as $old_name=>$new_name) {
339 $stmt_delete->execute(array($new_name));
340 $stmt_rename->execute(array($new_name, $old_name));
346 * php -r "include 'plugin/counter.inc.php'; plugin_counter_tool_setup_table();"
348 function plugin_counter_tool_setup_table() {
349 global $plugin_counter_db_options;
350 $page_counter_t = PLUGIN_COUNTER_DB_TABLE_NAME_PREFIX . 'page_counter';
351 $pdo = new PDO(PLUGIN_COUNTER_DB_CONNECT_STRING,
352 PLUGIN_COUNTER_DB_USERNAME, PLUGIN_COUNTER_DB_PASSWORD,
353 $plugin_counter_db_options);
354 $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
355 $pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
357 "CREATE TABLE $page_counter_t (
358 page_name VARCHAR(190) PRIMARY KEY,
359 total INTEGER NOT NULL,
360 update_date VARCHAR(20) NOT NULL,
361 today_viewcount INTEGER NOT NULL,
362 yesterday_viewcount INTEGER NOT NULL,
363 remote_addr VARCHAR(100)