From 5e75ad3cd429e5e0321cd9319228f8ed1e000ed7 Mon Sep 17 00:00:00 2001
From: Shish <webmaster@shishnet.org>
Date: Mon, 19 Jan 2009 10:18:23 -0800
Subject: [PATCH 1/5] start of cache engines

---
 core/database.class.php | 50 +++++++++++++++++++++++++++++++++++++++--
 1 file changed, 48 insertions(+), 2 deletions(-)

diff --git a/core/database.class.php b/core/database.class.php
index 05af31e2..5e3afea4 100644
--- a/core/database.class.php
+++ b/core/database.class.php
@@ -49,7 +49,7 @@ class ImgQuerylet {
 	}
 }
 // }}}
-// {{{ dbengines
+// {{{ db engines
 class DBEngine {
 	var $name = null;
 	var $auto_increment = null;
@@ -71,7 +71,43 @@ class PostgreSQL extends DBEngine {
 	function init($db) {
 	}
 }
-//}}}
+// }}}
+// {{{ cache engines
+interface CacheEngine {
+	var $db;
+	public function cache_get($key);
+	public function cache_set($key, $val, $time);
+	public function cache_delete($key);
+}
+class MemCache implements CacheEngine {
+	public function __construct(Database $db) {
+		$this->db = $db;
+	}
+
+	public function cache_get($key) {
+		assert(!is_null($key));
+		$val = $this->db->memcache->get($key);
+		if($val) {
+			$this->cache_hits++;
+			return $val;
+		}
+		else {
+			$this->cache_misses++;
+			return false;
+		}
+	}
+
+	public function cache_set($key, $val, $time=0) {
+		assert(!is_null($key));
+		$this->db->memcache->set($key, $val, false, $time);
+	}
+
+	public function cache_delete($key) {
+		assert(!is_null($key));
+		$this->db->memcache->delete($key);
+	}
+}
+// }}}
 
 /*
  * A class for controlled database access
@@ -81,6 +117,7 @@ class Database {
 	var $extensions;
 	var $cache_hits = 0, $cache_misses = 0;
 	var $engine = null;
+	var $cache = null;
 
 	/*
 	 * Create a new database object using connection info
@@ -92,6 +129,15 @@ class Database {
 			$this->engine = new MySQL();
 			$this->db = @NewADOConnection($database_dsn);
 			$this->use_memcache = isset($memcache);
+
+			if(isset($memcache)) {
+				$this->cache = new MemCache($this);
+			}
+			if(isset($cache)) {
+				//$matches = array();
+				//preg_match("#(memcache)://#", $cache, $matches);
+			}
+
 			if($this->db) {
 				$this->db->SetFetchMode(ADODB_FETCH_ASSOC);
 				$this->engine->init($this->db);

From 776a42d519e4b5407ff1d6d88f8eb835d21d8f58 Mon Sep 17 00:00:00 2001
From: Shish <webmaster@shishnet.org>
Date: Tue, 20 Jan 2009 02:47:20 -0800
Subject: [PATCH 2/5] cache objects

---
 contrib/ipban/main.php   |  6 +--
 core/config.class.php    |  6 +--
 core/database.class.php  | 84 ++++++++++++++--------------------------
 core/imageboard.pack.php | 10 ++---
 4 files changed, 40 insertions(+), 66 deletions(-)

diff --git a/contrib/ipban/main.php b/contrib/ipban/main.php
index 48c7e106..94344b88 100644
--- a/contrib/ipban/main.php
+++ b/contrib/ipban/main.php
@@ -204,7 +204,7 @@ class IPBan implements Extension {
 	private function get_active_bans() {
 		global $database;
 
-		$cached = $database->cache_get("bans");
+		$cached = $database->cache->get("bans");
 		if($cached) return $cached;
 
 		$bans = $database->get_all("
@@ -215,7 +215,7 @@ class IPBan implements Extension {
 			ORDER BY end_timestamp, id
 		");
 
-		$database->cache_set("bans", $bans);
+		$database->cache->set("bans", $bans);
 
 		if($bans) {return $bans;}
 		else {return array();}
@@ -225,7 +225,7 @@ class IPBan implements Extension {
 		global $database;
 		$sql = "INSERT INTO bans (ip, reason, end_timestamp, banner_id) VALUES (?, ?, ?, ?)";
 		$database->Execute($sql, array($ip, $reason, strtotime($end), $user->id));
-		$database->cache_delete("bans");
+		$database->cache->delete("bans");
 	}
 // }}}
 }
diff --git a/core/config.class.php b/core/config.class.php
index a33f31bc..50be4250 100644
--- a/core/config.class.php
+++ b/core/config.class.php
@@ -124,13 +124,13 @@ class DatabaseConfig extends BaseConfig {
 	public function DatabaseConfig($database) {
 		$this->database = $database;
 
-		$cached = $database->cache_get("config");
+		$cached = $database->cache->get("config");
 		if($cached) {
 			$this->values = $cached;
 		}
 		else {
 			$this->values = $this->database->db->GetAssoc("SELECT name, value FROM config");
-			$database->cache_set("config", $this->values);
+			$database->cache->set("config", $this->values);
 		}
 	}
 
@@ -147,7 +147,7 @@ class DatabaseConfig extends BaseConfig {
 			$this->database->Execute("DELETE FROM config WHERE name = ?", array($name));
 			$this->database->Execute("INSERT INTO config VALUES (?, ?)", array($name, $this->values[$name]));
 		}
-		$database->cache_delete("config");
+		$database->cache->delete("config");
 	}
 }
 ?>
diff --git a/core/database.class.php b/core/database.class.php
index 5e3afea4..54839976 100644
--- a/core/database.class.php
+++ b/core/database.class.php
@@ -74,37 +74,44 @@ class PostgreSQL extends DBEngine {
 // }}}
 // {{{ cache engines
 interface CacheEngine {
-	var $db;
-	public function cache_get($key);
-	public function cache_set($key, $val, $time);
-	public function cache_delete($key);
+	var $hits = 0, $misses = 0;
+
+	public function get($key);
+	public function set($key, $val, $time);
+	public function delete($key);
+}
+class NoCache implements CacheEngine {
+	public function get($key) {return false;}
+	public function set($key) {}
+	public function delete($key) {}
 }
 class MemCache implements CacheEngine {
-	public function __construct(Database $db) {
-		$this->db = $db;
+	public function __construct($args) {
+		$this->memcache = new Memcache;
+		$this->memcache->pconnect('localhost', 11211) or ($this->use_memcache = false);
 	}
 
-	public function cache_get($key) {
+	public function get($key) {
 		assert(!is_null($key));
-		$val = $this->db->memcache->get($key);
+		$val = $this->memcache->get($key);
 		if($val) {
-			$this->cache_hits++;
+			$this->hits++;
 			return $val;
 		}
 		else {
-			$this->cache_misses++;
+			$this->misses++;
 			return false;
 		}
 	}
 
-	public function cache_set($key, $val, $time=0) {
+	public function set($key, $val, $time=0) {
 		assert(!is_null($key));
-		$this->db->memcache->set($key, $val, false, $time);
+		$this->memcache->set($key, $val, false, $time);
 	}
 
-	public function cache_delete($key) {
+	public function delete($key) {
 		assert(!is_null($key));
-		$this->db->memcache->delete($key);
+		$this->memcache->delete($key);
 	}
 }
 // }}}
@@ -115,7 +122,6 @@ class MemCache implements CacheEngine {
 class Database {
 	var $db;
 	var $extensions;
-	var $cache_hits = 0, $cache_misses = 0;
 	var $engine = null;
 	var $cache = null;
 
@@ -128,14 +134,16 @@ class Database {
 			require_once "config.php";
 			$this->engine = new MySQL();
 			$this->db = @NewADOConnection($database_dsn);
-			$this->use_memcache = isset($memcache);
 
-			if(isset($memcache)) {
-				$this->cache = new MemCache($this);
-			}
 			if(isset($cache)) {
-				//$matches = array();
-				//preg_match("#(memcache)://#", $cache, $matches);
+				$matches = array();
+				preg_match("#(memcache)://(.*)#", $cache, $matches);
+				if($matches[1] == "memcache") {
+					$this->cache = new MemCache($matches[2]);
+				}
+			}
+			else {
+				$this->cache = new NoCache();
 			}
 
 			if($this->db) {
@@ -156,10 +164,6 @@ class Database {
 				";
 				exit;
 			}
-			if($this->use_memcache) {
-				$this->memcache = new Memcache;
-				$this->memcache->pconnect('localhost', 11211) or ($this->use_memcache = false);
-			}
 		}
 		else {
 			header("Location: install.php");
@@ -167,36 +171,6 @@ class Database {
 		}
 	}
 
-// memcache {{{
-	public function cache_get($key) {
-		assert(!is_null($key));
-		if($this->use_memcache) {
-			$val = $this->memcache->get($key);
-			if($val) {
-				$this->cache_hits++;
-				return $val;
-			}
-			else {
-				$this->cache_misses++;
-			}
-		}
-		return false;
-	}
-
-	public function cache_set($key, $val, $time=0) {
-		assert(!is_null($key));
-		if($this->use_memcache) {
-			$this->memcache->set($key, $val, false, $time);
-		}
-	}
-
-	public function cache_delete($key) {
-		assert(!is_null($key));
-		if($this->use_memcache) {
-			$this->memcache->delete($key);
-		}
-	}
-// }}}
 // safety wrapping {{{
 	public function execute($query, $args=array()) {
 		$result = $this->db->Execute($query, $args);
diff --git a/core/imageboard.pack.php b/core/imageboard.pack.php
index 0f38d6e1..3d1f1945 100644
--- a/core/imageboard.pack.php
+++ b/core/imageboard.pack.php
@@ -144,7 +144,7 @@ class Image {
 	}
 
 	public function get_tag_array() {
-		$cached = $this->database->cache_get("image-{$this->id}-tags");
+		$cached = $this->database->cache->get("image-{$this->id}-tags");
 		if($cached) return $cached;
 
 		if(!isset($this->tag_array)) {
@@ -156,7 +156,7 @@ class Image {
 			}
 		}
 
-		$this->database->cache_set("image-{$this->id}-tags", $this->tag_array);
+		$this->database->cache->set("image-{$this->id}-tags", $this->tag_array);
 		return $this->tag_array;
 	}
 
@@ -267,7 +267,7 @@ class Image {
 					array($tag));
 		}
 
-		$this->database->cache_delete("image-{$this->id}-tags");
+		$this->database->cache->delete("image-{$this->id}-tags");
 	}
 
 
@@ -528,8 +528,8 @@ function get_debug_info() {
 	$i_files = count(get_included_files());
 	global $_execs;
 	global $database;
-	$hits = $database->cache_hits;
-	$miss = $database->cache_misses;
+	$hits = $database->cache->hits;
+	$miss = $database->cache->misses;
 	$debug = "<br>Took $i_utime + $i_stime seconds and {$i_mem}MB of RAM";
 	$debug .= "; Used $i_files files and $_execs queries";
 	$debug .= "; Sent $_event_count events";

From 6e6a6bdd16b1cd33a5bd1e70c1d42d879b283e83 Mon Sep 17 00:00:00 2001
From: Shish <webmaster@shishnet.org>
Date: Tue, 20 Jan 2009 03:17:49 -0800
Subject: [PATCH 3/5] scoreyness

---
 core/page.class.php              | 2 +-
 themes/danbooru/layout.class.php | 6 ++++--
 themes/default/layout.class.php  | 6 ++++--
 themes/futaba/layout.class.php   | 6 ++++--
 themes/minimal/layout.class.php  | 6 ++++--
 5 files changed, 17 insertions(+), 9 deletions(-)

diff --git a/core/page.class.php b/core/page.class.php
index 3bd5c2ca..b22fff3c 100644
--- a/core/page.class.php
+++ b/core/page.class.php
@@ -79,7 +79,7 @@ class GenericPage {
 				header("Cache-control: no-cache");
 				usort($this->blocks, "blockcmp");
 				$layout = new Layout();
-				$layout->display_page($this);
+				$layout->display_page($context);
 				break;
 			case "data":
 				if(!is_null($this->filename)) {
diff --git a/themes/danbooru/layout.class.php b/themes/danbooru/layout.class.php
index b3320201..4231da2a 100644
--- a/themes/danbooru/layout.class.php
+++ b/themes/danbooru/layout.class.php
@@ -42,8 +42,10 @@ Tips
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
 class Layout {
-	public function display_page($page) {
-		global $config;
+	public function display_page($context) {
+		$page = $context->page;
+		$config = $context->config;
+
 		$theme_name = $config->get_string('theme');
 		$base_href = $config->get_string('base_href');
 		$data_href = get_base_href();
diff --git a/themes/default/layout.class.php b/themes/default/layout.class.php
index 07b61a72..167011c8 100644
--- a/themes/default/layout.class.php
+++ b/themes/default/layout.class.php
@@ -1,8 +1,10 @@
 <?php
 
 class Layout {
-	function display_page($page) {
-		global $config;
+	function display_page($context) {
+		$page = $context->page;
+		$config = $context->config;
+
 		$theme_name = $config->get_string('theme', 'default');
 		$data_href = get_base_href();
 		$contact_link = $config->get_string('contact_link');
diff --git a/themes/futaba/layout.class.php b/themes/futaba/layout.class.php
index a1d27860..0a6ea41c 100644
--- a/themes/futaba/layout.class.php
+++ b/themes/futaba/layout.class.php
@@ -1,8 +1,10 @@
 <?php
 
 class Layout {
-	function display_page($page) {
-		global $config;
+	function display_page($context) {
+		$page = $context->page;
+		$config = $context->config;
+
 		$theme_name = $config->get_string('theme', 'default');
 		$data_href = get_base_href();
 		$contact_link = $config->get_string('contact_link');
diff --git a/themes/minimal/layout.class.php b/themes/minimal/layout.class.php
index 4a62a41d..306da52f 100644
--- a/themes/minimal/layout.class.php
+++ b/themes/minimal/layout.class.php
@@ -1,8 +1,10 @@
 <?php
 
 class Layout {
-	function display_page($page) {
-		global $config;
+	function display_page($context) {
+		$page = $context->page;
+		$config = $context->config;
+
 		$theme_name = $config->get_string('theme', 'default');
 		$data_href = get_base_href();
 		$contact_link = $config->get_string('contact_link');

From 03bee56193534303e70a3c329ac8090b63c48a08 Mon Sep 17 00:00:00 2001
From: Shish <webmaster@shishnet.org>
Date: Tue, 20 Jan 2009 03:24:35 -0800
Subject: [PATCH 4/5] move extension specific parts out of user and into
 extensions

---
 core/user.class.php  | 14 --------------
 ext/comment/main.php |  5 +++++
 ext/user/theme.php   |  9 +++------
 3 files changed, 8 insertions(+), 20 deletions(-)

diff --git a/core/user.class.php b/core/user.class.php
index ddc3aceb..ce7691a1 100644
--- a/core/user.class.php
+++ b/core/user.class.php
@@ -84,19 +84,5 @@ class User {
 		$hash = md5(strtolower($this->name) . $password);
 		$this->database->Execute("UPDATE users SET pass=? WHERE id=?", array($hash, $this->id));
 	}
-
-	public function get_days_old() {
-		return 0; // FIXME calculate this
-	}
-
-	public function get_image_count() {
-		global $database;
-		return $database->db->GetOne("SELECT COUNT(*) AS count FROM images WHERE owner_id=?", array($this->id));
-	}
-
-	public function get_comment_count() {
-		global $database;
-		return $database->db->GetOne("SELECT COUNT(*) AS count FROM comments WHERE owner_id=?", array($this->id));
-	}
 }
 ?>
diff --git a/ext/comment/main.php b/ext/comment/main.php
index 70348a30..607d71f2 100644
--- a/ext/comment/main.php
+++ b/ext/comment/main.php
@@ -47,6 +47,11 @@ class Comment { // {{{
 		$this->poster_ip =  $row['poster_ip'];
 		$this->posted =  $row['posted'];
 	}
+
+	public static function count_comments_by_user($user) {
+		global $database;
+		return $database->db->GetOne("SELECT COUNT(*) AS count FROM comments WHERE owner_id=?", array($user->id));
+	}
 } // }}}
 
 class CommentList implements Extension {
diff --git a/ext/user/theme.php b/ext/user/theme.php
index f26c8809..e5024ab4 100644
--- a/ext/user/theme.php
+++ b/ext/user/theme.php
@@ -122,12 +122,9 @@ class UserPageTheme extends Themelet {
 		global $database;
 		global $config;
 
-		$i_days_old = int_escape($duser->get_days_old());
 		$h_join_date = html_escape($duser->join_date);
-		$i_image_count = int_escape($duser->get_image_count());
-		$i_comment_count = int_escape($duser->get_comment_count());
-
-		$i_days_old2 = ($i_days_old == 0) ? 1 : $i_days_old;
+		$i_image_count = Image::count_images($config, $database, array("user_id={$duser->id}"));
+		$i_comment_count = Comment::count_comments_by_user($duser);
 
 		$h_image_rate = sprintf("%3.1f", ($i_image_count / $i_days_old2));
 		$h_comment_rate = sprintf("%3.1f", ($i_comment_count / $i_days_old2));
@@ -136,7 +133,7 @@ class UserPageTheme extends Themelet {
 		$images_link = make_link("post/list/user_id=$u_id/1");
 
 		return "
-			Join date: $h_join_date ($i_days_old days old)
+			Join date: $h_join_date
 			<br><a href='$images_link'>Images uploaded</a>: $i_image_count ($h_image_rate / day)
 			<br>Comments made: $i_comment_count ($h_comment_rate / day)
 			";

From fcca11f20c8aa3eb8ba55d727cfddf12501d7132 Mon Sep 17 00:00:00 2001
From: Shish <webmaster@shishnet.org>
Date: Tue, 20 Jan 2009 03:54:43 -0800
Subject: [PATCH 5/5] make cache engines work <_<

---
 core/database.class.php  | 17 +++++++++++++----
 core/imageboard.pack.php |  4 ++--
 2 files changed, 15 insertions(+), 6 deletions(-)

diff --git a/core/database.class.php b/core/database.class.php
index 54839976..15bf2133 100644
--- a/core/database.class.php
+++ b/core/database.class.php
@@ -74,18 +74,24 @@ class PostgreSQL extends DBEngine {
 // }}}
 // {{{ cache engines
 interface CacheEngine {
-	var $hits = 0, $misses = 0;
-
 	public function get($key);
-	public function set($key, $val, $time);
+	public function set($key, $val, $time=0);
 	public function delete($key);
+
+	public function get_hits();
+	public function get_misses();
 }
 class NoCache implements CacheEngine {
 	public function get($key) {return false;}
-	public function set($key) {}
+	public function set($key, $val, $time=0) {}
 	public function delete($key) {}
+
+	public function get_hits() {return 0;}
+	public function get_misses() {return 0;}
 }
 class MemCache implements CacheEngine {
+	var $hits=0, $misses=0;
+
 	public function __construct($args) {
 		$this->memcache = new Memcache;
 		$this->memcache->pconnect('localhost', 11211) or ($this->use_memcache = false);
@@ -113,6 +119,9 @@ class MemCache implements CacheEngine {
 		assert(!is_null($key));
 		$this->memcache->delete($key);
 	}
+
+	public function get_hits() {return $this->hits;}
+	public function get_misses() {return $this->misses;}
 }
 // }}}
 
diff --git a/core/imageboard.pack.php b/core/imageboard.pack.php
index 3d1f1945..13e3cd71 100644
--- a/core/imageboard.pack.php
+++ b/core/imageboard.pack.php
@@ -528,8 +528,8 @@ function get_debug_info() {
 	$i_files = count(get_included_files());
 	global $_execs;
 	global $database;
-	$hits = $database->cache->hits;
-	$miss = $database->cache->misses;
+	$hits = $database->cache->get_hits();
+	$miss = $database->cache->get_misses();
 	$debug = "<br>Took $i_utime + $i_stime seconds and {$i_mem}MB of RAM";
 	$debug .= "; Used $i_files files and $_execs queries";
 	$debug .= "; Sent $_event_count events";