2 // PukiWiki - Yet another WikiWikiWeb clone
5 // 2002-2017 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 $plugin_counter_db_options = null;
21 // $plugin_counter_db_options = array(PDO::MYSQL_ATTR_INIT_COMMAND =>
22 // "SET NAMES utf8mb4 COLLATE utf8mb4_bin");
24 define('PLUGIN_COUNTER_DB_TABLE_NAME_PREFIX', '');
26 if (PLUGIN_COUNTER_USE_DB) {
27 ini_set('default_socket_timeout', 2);
31 function plugin_counter_inline()
35 // BugTrack2/106: Only variables can be passed by reference from PHP 5.0.5
36 $args = func_get_args(); // with array_shift()
38 $arg = strtolower(array_shift($args));
40 case '' : $arg = 'total'; /*FALLTHROUGH*/
41 case 'total': /*FALLTHROUGH*/
42 case 'today': /*FALLTHROUGH*/
44 $counter = plugin_counter_get_count($vars['page']);
45 return $counter[$arg];
47 return '&counter([total|today|yesterday]);';
52 function plugin_counter_convert()
56 $counter = plugin_counter_get_count($vars['page']);
59 Counter: {$counter['total']},
60 today: {$counter['today']},
61 yesterday: {$counter['yesterday']}
67 function plugin_counter_get_count($page)
69 global $vars, $plugin_counter_db_options;
70 static $counters = array();
72 $page_counter_t = PLUGIN_COUNTER_DB_TABLE_NAME_PREFIX . 'page_counter';
74 if (! isset($default))
77 'date' => get_date('Y/m/d'),
82 if (! is_page($page)) return $default;
83 if (isset($counters[$page])) return $counters[$page];
86 $counters[$page] = $default;
88 $c = & $counters[$page];
90 if (PLUGIN_COUNTER_USE_DB) {
91 if (SOURCE_ENCODING !== 'UTF-8') {
92 die('counter.inc.php: Database counter is only available in UTF-8 mode');
96 $pdo = new PDO(PLUGIN_COUNTER_DB_CONNECT_STRING,
97 PLUGIN_COUNTER_DB_USERNAME, PLUGIN_COUNTER_DB_PASSWORD,
98 $plugin_counter_db_options);
99 $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
100 $pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
101 $pdo->setAttribute(PDO::ATTR_TIMEOUT, 5);
102 $stmt = $pdo->prepare(
103 "SELECT total, update_date,
104 today_viewcount, yesterday_viewcount, remote_addr
108 $stmt->execute(array($page));
113 $c['ip'] = $r['remote_addr'];
114 $c['date'] = $r['update_date'];
115 $c['yesterday'] = intval($r['yesterday_viewcount']);
116 $c['today'] = intval($r['today_viewcount']);
117 $c['total'] = intval($r['total']);
118 $stmt->closeCursor();
120 } catch (Exception $e) {
122 $db_error = '(DBError)';
124 'total' => $db_error,
126 'today' => $db_error,
127 'yesterday' => $db_error,
132 $file = COUNTER_DIR . encode($page) . PLUGIN_COUNTER_SUFFIX;
133 pkwk_touch_file($file);
134 $fp = fopen($file, 'r+')
135 or die('counter.inc.php: Cannot open COUNTER_DIR/' . basename($file));
136 set_file_buffer($fp, 0);
141 foreach (array_keys($default) as $key) {
143 $c[$key] = rtrim(fgets($fp, 256));
144 if (feof($fp)) break;
149 $remote_addr = $_SERVER['REMOTE_ADDR'];
151 if ($c['date'] != $default['date']) {
153 $is_yesterday = ($c['date'] == get_date('Y/m/d', UTIME - 24 * 60 * 60));
154 $c[$page]['ip'] = $remote_addr;
155 $c['date'] = $default['date'];
156 $c['yesterday'] = $is_yesterday ? $c['today'] : 0;
160 } else if ($c['ip'] != $remote_addr) {
163 $c['ip'] = $remote_addr;
169 if (PLUGIN_COUNTER_USE_DB) {
170 if ($modify && $vars['cmd'] == 'read') {
174 $add_stmt = $pdo->prepare(
175 "INSERT INTO $page_counter_t
176 (page_name, total, update_date, today_viewcount,
177 yesterday_viewcount, remote_addr)
178 VALUES (?, ?, ?, ?, ?, ?)"
180 $r_add = $add_stmt->execute(array($page, $c['total'],
181 $c['date'], $c['today'], $c['yesterday'], $c['ip']));
182 } else if ($count_up) {
183 // Update on counting up 'total'
184 $upd_stmt = $pdo->prepare(
185 "UPDATE $page_counter_t
186 SET total = total + 1,
189 yesterday_viewcount = ?,
193 $r_upd = $upd_stmt->execute(array($c['date'],
194 $c['today'], $c['yesterday'], $c['ip'], $page));
196 } catch (PDOException $e) {
197 foreach (array_keys($c) as $key) {
198 $c[$key] .= '(DBError)';
204 if ($modify && $vars['cmd'] == 'read') {
207 foreach (array_keys($default) as $key)
208 fputs($fp, $c[$key] . "\n");
217 function plugin_counter_get_popular_list($today, $except, $max) {
218 if (PLUGIN_COUNTER_USE_DB === 0) {
219 return plugin_counter_get_popular_list_file($today, $except, $max);
221 return plugin_counter_get_popular_list_db($today, $except, $max);
225 function plugin_counter_get_popular_list_file($today, $except, $max) {
228 $except_quote = str_replace('#', '\#', $except);
229 foreach (get_existpages(COUNTER_DIR, '.count') as $file=>$page) {
230 if (($except != '' && preg_match("#$except_quote#", $page)) ||
231 $page == $whatsnew || check_non_list($page) ||
235 $array = file(COUNTER_DIR . $file);
236 $count = rtrim($array[0]);
237 $date = rtrim($array[1]);
238 $today_count = rtrim($array[2]);
241 // $pageが数値に見える(たとえばencode('BBS')=424253)とき、
242 // array_splice()によってキー値が変更されてしまうのを防ぐ
244 if ($today == $date) $counters['_' . $page] = $today_count;
246 $counters['_' . $page] = $count;
250 asort($counters, SORT_NUMERIC);
252 // BugTrack2/106: Only variables can be passed by reference from PHP 5.0.5
253 $counters = array_reverse($counters, TRUE); // with array_splice()
254 $counters = array_splice($counters, 0, $max);
258 function plugin_counter_get_popular_list_db($today, $except, $max) {
260 $page_counter_t = PLUGIN_COUNTER_DB_TABLE_NAME_PREFIX . 'page_counter';
262 $order_by_c = 'today_viewcount';
264 $order_by_c = 'total';
268 $pdo = new PDO(PLUGIN_COUNTER_DB_CONNECT_STRING,
269 PLUGIN_COUNTER_DB_USERNAME, PLUGIN_COUNTER_DB_PASSWORD,
270 $plugin_counter_db_options);
271 $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
272 $pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
273 $pdo->setAttribute(PDO::ATTR_TIMEOUT, 5);
275 $stmt = $pdo->prepare(
276 "SELECT page_name, total, update_date,
277 today_viewcount, yesterday_viewcount
279 WHERE update_date = ?
280 ORDER BY $order_by_c DESC
284 $stmt = $pdo->prepare(
285 "SELECT page_name, total, update_date,
286 today_viewcount, yesterday_viewcount
288 ORDER BY $order_by_c DESC
292 $except_quote = str_replace('#', '\#', $except);
295 $stmt->execute(array($today, $limit));
297 $stmt->execute(array($limit));
299 foreach ($stmt as $r) {
300 $page = $r['page_name'];
301 if (($except != '' && preg_match("#$except_quote#", $page)) ||
302 $page == $whatsnew || check_non_list($page) ||
307 $counters['_' . $page] = $r['today_viewcount'];
309 $counters['_' . $page] = $r['total'];
312 $stmt->closeCursor();
313 return array_splice($counters, 0, $max);
314 } catch (Exception $e) {
315 die('counter.inc.php: Error occurred on getting pupular pages');
319 function plugin_counter_page_rename($pages) {
320 global $plugin_counter_db_options;
321 if (PLUGIN_COUNTER_USE_DB !== 0) {
322 $page_counter_t = PLUGIN_COUNTER_DB_TABLE_NAME_PREFIX . 'page_counter';
323 $pdo = new PDO(PLUGIN_COUNTER_DB_CONNECT_STRING,
324 PLUGIN_COUNTER_DB_USERNAME, PLUGIN_COUNTER_DB_PASSWORD,
325 $plugin_counter_db_options);
326 $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
327 $pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
328 $stmt_delete = $pdo->prepare(
329 "DELETE FROM $page_counter_t
332 $stmt_rename = $pdo->prepare(
333 "UPDATE $page_counter_t
337 foreach ($pages as $old_name=>$new_name) {
338 $stmt_delete->execute(array($new_name));
339 $stmt_rename->execute(array($new_name, $old_name));
345 * php -r "include 'plugin/counter.inc.php'; plugin_counter_tool_setup_table();"
347 function plugin_counter_tool_setup_table() {
348 global $plugin_counter_db_options;
349 $page_counter_t = PLUGIN_COUNTER_DB_TABLE_NAME_PREFIX . 'page_counter';
350 $pdo = new PDO(PLUGIN_COUNTER_DB_CONNECT_STRING,
351 PLUGIN_COUNTER_DB_USERNAME, PLUGIN_COUNTER_DB_PASSWORD,
352 $plugin_counter_db_options);
353 $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
354 $pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
356 "CREATE TABLE $page_counter_t (
357 page_name VARCHAR(190) PRIMARY KEY,
358 total INTEGER NOT NULL,
359 update_date VARCHAR(20) NOT NULL,
360 today_viewcount INTEGER NOT NULL,
361 yesterday_viewcount INTEGER NOT NULL,
362 remote_addr VARCHAR(100)