OSDN Git Service

BugTrack/2422 Use SQLite database for reliable counter
authorumorigu <umorigu@gmail.com>
Sat, 27 May 2017 03:07:04 +0000 (12:07 +0900)
committerumorigu <umorigu@gmail.com>
Sat, 27 May 2017 13:38:46 +0000 (22:38 +0900)
.gitignore
plugin/counter.inc.php

index 894a042..869577a 100644 (file)
 /cache/*.ref
 /cache/*.rel
 /counter/*.count
+/counter/*.db
+
 /diff/*.txt
 /wiki/*.txt
 /wiki.en/*.txt
 
 /nbproject/**
 
+# Composer files
+/vendor/
+
index 35f1230..9cab659 100644 (file)
@@ -1,8 +1,8 @@
 <?php
 // PukiWiki - Yet another WikiWikiWeb clone
-// $Id: counter.inc.php,v 1.19 2007/02/04 11:14:44 henoheno Exp $
-// Copyright (C)
-//   2002-2005, 2007 PukiWiki Developers Team
+// counter.inc.php
+// Copyright
+//   2002-2017 PukiWiki Development Team
 //   2002 Y.MASUI GPL2 http://masui.net/pukiwiki/ masui@masui.net
 // License: GPL2
 //
 
 // Counter file's suffix
 define('PLUGIN_COUNTER_SUFFIX', '.count');
+// Use Database (1) or not (0)
+define('PLUGIN_COUNTER_USE_DB', 0);
+// Database Connection string
+define('PLUGIN_COUNTER_DB_CONNECT_STRING', 'sqlite:counter/counter.db');
+define('PLUGIN_COUNTER_DB_USERNAME', '');
+define('PLUGIN_COUNTER_DB_PASSWORD', '');
+define('PLUGIN_COUNTER_DB_OPTIONS', null);
 
 // Report one
 function plugin_counter_inline()
@@ -68,51 +75,135 @@ function plugin_counter_get_count($page)
        // Set default
        $counters[$page] = $default;
        $modify = FALSE;
+       $c = & $counters[$page];
+
+       if (PLUGIN_COUNTER_USE_DB) {
+               if (SOURCE_ENCODING !== 'UTF-8') {
+                       die('counter.inc.php: Database counter is only available in UTF-8 mode');
+               }
+               $is_new_page = false;
+               try {
+                       $pdo = new PDO(PLUGIN_COUNTER_DB_CONNECT_STRING,
+                               PLUGIN_COUNTER_DB_USERNAME, PLUGIN_COUNTER_DB_PASSWORD,
+                               PLUGIN_COUNTER_DB_OPTIONS);
+                       $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+                       $pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
+                       $pdo->setAttribute(PDO::ATTR_TIMEOUT, 5);
+                       $stmt = $pdo->prepare('SELECT total, update_date,
+                                       today_viewcount, yesterday_viewcount, remote_addr
+                               FROM page_counter WHERE page_name = ?');
+                       $stmt->execute(array($page));
+                       $r = $stmt->fetch();
+                       if ($r === false) {
+                               $is_new_page = true;
+                       } else {
+                               $c['ip'] = $r['remote_addr'];
+                               $c['date'] = $r['update_date'];
+                               $c['yesterday'] = intval($r['yesterday_viewcount']);
+                               $c['today'] = intval($r['today_viewcount']);
+                               $c['total'] = intval($r['total']);
+                               $stmt->closeCursor();
+                       }
+               } catch (Exception $e) {
+                       die('counter.inc.php: Error occurred');
+               }
+       } else {
+               // Open
+               $file = COUNTER_DIR . encode($page) . PLUGIN_COUNTER_SUFFIX;
+               pkwk_touch_file($file);
+               $fp = fopen($file, 'r+')
+                       or die('counter.inc.php: Cannot open COUNTER_DIR/' . basename($file));
+               set_file_buffer($fp, 0);
+               flock($fp, LOCK_EX);
+               rewind($fp);
 
-       // Open
-       $file = COUNTER_DIR . encode($page) . PLUGIN_COUNTER_SUFFIX;
-       pkwk_touch_file($file);
-       $fp = fopen($file, 'r+')
-               or die('counter.inc.php: Cannot open COUNTER_DIR/' . basename($file));
-       set_file_buffer($fp, 0);
-       flock($fp, LOCK_EX);
-       rewind($fp);
-
-       // Read
-       foreach (array_keys($default) as $key) {
-               // Update
-               $counters[$page][$key] = rtrim(fgets($fp, 256));
-               if (feof($fp)) break;
+               // Read
+               foreach (array_keys($default) as $key) {
+                       // Update
+                       $c[$key] = rtrim(fgets($fp, 256));
+                       if (feof($fp)) break;
+               }
        }
 
        // Anothoer day?
-       if ($counters[$page]['date'] != $default['date']) {
+       $remote_addr = $_SERVER['REMOTE_ADDR'];
+       if ($c['date'] != $default['date']) {
                $modify = TRUE;
-               $is_yesterday = ($counters[$page]['date'] == get_date('Y/m/d', UTIME - 24 * 60 * 60));
-               $counters[$page]['ip']        = $_SERVER['REMOTE_ADDR'];
-               $counters[$page]['date']      = $default['date'];
-               $counters[$page]['yesterday'] = $is_yesterday ? $counters[$page]['today'] : 0;
-               $counters[$page]['today']     = 1;
-               $counters[$page]['total']++;
-       } else if ($counters[$page]['ip'] != $_SERVER['REMOTE_ADDR']) {
+               $is_yesterday = ($c['date'] == get_date('Y/m/d', UTIME - 24 * 60 * 60));
+               $c[$page]['ip']        = $remote_addr;
+               $c['date']      = $default['date'];
+               $c['yesterday'] = $is_yesterday ? $c['today'] : 0;
+               $c['today']     = 1;
+               $c['total']++;
+       } else if ($c['ip'] != $remote_addr) {
                // Not the same host
                $modify = TRUE;
-               $counters[$page]['ip']        = $_SERVER['REMOTE_ADDR'];
-               $counters[$page]['today']++;
-               $counters[$page]['total']++;
+               $c['ip']        = $remote_addr;
+               $c['today']++;
+               $c['total']++;
        }
 
-       // Modify
-       if ($modify && $vars['cmd'] == 'read') {
-               rewind($fp);
-               ftruncate($fp, 0);
-               foreach (array_keys($default) as $key)
-                       fputs($fp, $counters[$page][$key] . "\n");
+       if (PLUGIN_COUNTER_USE_DB) {
+               if ($modify && $vars['cmd'] == 'read') {
+                       try {
+                               if ($is_new_page) {
+                                       // Insert
+                                       $add_stmt = $pdo->prepare('INSERT INTO page_counter
+                                               (page_name, total, update_date, today_viewcount,
+                                                       yesterday_viewcount, remote_addr)
+                                               values (?, ?, ?, ?, ?, ?)');
+                                       $r_add = $add_stmt->execute(array($page, $c['total'],
+                                               $c['date'], $c['today'], $c['yesterday'], $c['ip']));
+                               } else {
+                                       // Update
+                                       $upd_stmt = $pdo->prepare('UPDATE page_counter
+                                               SET total = ?,
+                                                       update_date = ?,
+                                                       today_viewcount = ?,
+                                                       yesterday_viewcount = ?,
+                                                       remote_addr = ?
+                                               WHERE page_name = ?');
+                                       $r_upd = $upd_stmt->execute(array($c['total'],
+                                               $c['date'], $c['today'], $c['yesterday'], $c['ip'],
+                                               $page));
+                               }
+                       } catch (PDOException $e) {
+                               foreach (array_keys($c) as $key) {
+                                       $c[$key] .= '(DBError)';
+                               }
+                       }
+               }
+       } else {
+               // Modify
+               if ($modify && $vars['cmd'] == 'read') {
+                       rewind($fp);
+                       ftruncate($fp, 0);
+                       foreach (array_keys($default) as $key)
+                               fputs($fp, $c[$key] . "\n");
+               }
+               // Close
+               flock($fp, LOCK_UN);
+               fclose($fp);
        }
+       return $c;
+}
 
-       // Close
-       flock($fp, LOCK_UN);
-       fclose($fp);
-
-       return $counters[$page];
+/**
+ * php -r "include 'plugin/counter.inc.php'; plugin_counter_tool_setup_table();"
+ */
+function plugin_counter_tool_setup_table() {
+       $pdo = new PDO(PLUGIN_COUNTER_DB_CONNECT_STRING,
+               PLUGIN_COUNTER_DB_USERNAME, PLUGIN_COUNTER_DB_PASSWORD,
+               PLUGIN_COUNTER_DB_OPTIONS);
+       $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+       $pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
+       $r = $pdo->exec('CREATE TABLE page_counter (
+               page_name VARCHAR(300) PRIMARY KEY,
+               total INTEGER NOT NULL,
+               update_date VARCHAR(20) NOT NULL,
+               today_viewcount INTEGER NOT NULL,
+               yesterday_viewcount INTEGER NOT NULL,
+               remote_addr VARCHAR(100)
+       )');
+       echo "OK\n";
 }