Index: trunk/bin/module_maker/skel/admin.php
===================================================================
--- trunk/bin/module_maker/skel/admin.php	(revision 136)
+++ trunk/bin/module_maker/skel/admin.php	(revision 137)
@@ -19,6 +19,6 @@
 require_once 'codebase/lib/TemplateGlue.inc.php';
 require_once 'codebase/lib/Prefs.inc.php';
-require_once 'codebase/lib/RecordLock.inc.php';
-require_once 'codebase/lib/RecordVersion.inc.php';
+require_once 'codebase/lib/Lock.inc.php';
+require_once 'codebase/lib/Version.inc.php';
 %ADMIN_UPLOAD_INCLUDE%
 
@@ -294,5 +294,5 @@
 
     // Create version.
-    $version = RecordVersion::getInstance($GLOBALS['auth']);
+    $version = Version::getInstance($GLOBALS['auth']);
     $version->create('%DB_TBL%', '%PRIMARY_KEY%', $last_insert_id, $frm['<##>']);
 
@@ -319,5 +319,5 @@
 
     // Create version.
-    $version = RecordVersion::getInstance($GLOBALS['auth']);
+    $version = Version::getInstance($GLOBALS['auth']);
     $version->create('%DB_TBL%', '%PRIMARY_KEY%', $frm['%PRIMARY_KEY%'], $frm['<##>']);
 
Index: trunk/docs/file_layout.txt
===================================================================
--- trunk/docs/file_layout.txt	(revision 136)
+++ trunk/docs/file_layout.txt	(revision 137)
@@ -52,6 +52,6 @@
         PEdit.inc.php (page-by-page file-based content management system)
         Prefs.inc.php (class for semi-permenent storage of values)
-        RecordLock.inc.php (db record locking system)
-        RecordVersion.inc.php (db record versioning system)
+        Lock.inc.php (db record locking system)
+        Version.inc.php (db record versioning system)
         ScriptTimer.inc.php (timer for scripts)
         Cache.inc.php (class for accessing a cache in a users session, stores any variables for quick retreival)
Index: trunk/docs/revision_history.txt
===================================================================
--- trunk/docs/revision_history.txt	(revision 136)
+++ trunk/docs/revision_history.txt	(revision 137)
@@ -29,6 +29,6 @@
     - DB
     - DBSessionHandler
-    - RecordLock
-    - RecordVersion
+    - Lock
+    - Version
     - Cache
     - Upload
@@ -72,5 +72,5 @@
 Full test suite for all codebase libraries. Run from the command line: "codebase/tests/run_tests.sh;"
 
-Classes that access database tables have a function initDB() that will setup the basic schema necessary to run. This includes Auth_SQL, RecordVersion, RecordLock, and DBSessionHandler.
+Classes that access database tables have a function initDB() that will setup the basic schema necessary to run. This includes Auth_SQL, Version, Lock, and DBSessionHandler.
 
 And much much more still to document...
Index: trunk/lib/Cache.inc.php
===================================================================
--- trunk/lib/Cache.inc.php	(revision 137)
+++ trunk/lib/Cache.inc.php	(revision 137)
@@ -0,0 +1,203 @@
+<?php
+/**
+ * Cache.inc.php
+ * code by strangecode :: www.strangecode.com :: this document contains copyrighted information
+ *
+ * Provides an API for storing a limited amount of data
+ * intended to have a short lifetime in a user's session.
+ *
+ * @author  Quinn Comendant <quinn@strangecode.com>
+ * @version 2.1
+ * @since   2001
+ */
+ 
+// Flags.
+define('CACHE_IGNORE_SIZE', 1);
+
+class Cache {
+
+    var $_params = array(
+        'enabled' => true,
+        'soft_limit' => 204800,
+        'hard_limit' => 4194304,
+        'min_items' => 3,
+    );
+
+    /**
+     * This method enforces the singleton pattern for this class.
+     *
+     * @return  object  Reference to the global Cache object.
+     * @access  public
+     * @static
+     */
+    function &getInstance()
+    {
+        static $instance = null;
+
+        if ($instance === null) {
+            $instance = new Cache();
+        }
+
+        return $instance;
+    }
+
+    /**
+     * Set (or overwrite existing) parameters by passing an array of new parameters.
+     *
+     * @access public
+     * @param  array    $params     Array of parameters (key => val pairs).
+     */
+    function setParam($params)
+    {
+		$app =& App::getInstance();
+
+        if (isset($params) && is_array($params)) {
+            // Merge new parameters with old overriding only those passed.
+            $this->_params = array_merge($this->_params, $params);
+        } else {
+            $app->logMsg(sprintf('Parameters are not an array: %s', $params), LOG_ERR, __FILE__, __LINE__);
+        }
+    }
+
+    /**
+     * Return the value of a parameter, if it exists.
+     *
+     * @access public
+     * @param string $param        Which parameter to return.
+     * @return mixed               Configured parameter value.
+     */
+    function getParam($param)
+    {
+		$app =& App::getInstance();
+    
+        if (isset($this->_params[$param])) {
+            return $this->_params[$param];
+        } else {
+            $app->logMsg(sprintf('Parameter is not set: %s', $param), LOG_NOTICE, __FILE__, __LINE__);
+            return null;
+        }
+    }
+
+    /**
+     * Stores a new variable in the session cache. The $key is is md5'ed
+     * because if a variable id is a very large integer, the array_shift function
+     * will reset the key to the next largest int key. Weird behavior I can't
+     * understand. $session_cache[32341234123] will become $session_cache[0]
+     * for example. Usage warning: if the variable is too big to fit, or is
+     * old and discarded, you must provide alternative ways of accessing the data.
+     *
+     * @param str   $key        An identifier for the cached object.
+     * @param mixed $var          The var to store in the session cache.
+     * @param bool  $flags      If we have something really big that we
+     *                            still want to cache, setting this to
+     *                            CACHE_IGNORE_SIZE allows this.
+     *
+     * @return bool               True on success, false otherwise.
+     */
+    function set($key, $var, $flags=0)
+    {
+		$app =& App::getInstance();
+
+        if (!$this->getParam('enabled')) {
+            $app->logMsg(sprintf('Cache not enabled, not saving data.', null), LOG_DEBUG, __FILE__, __LINE__);
+            return false;
+        }
+
+        $key = md5($key);
+        $serialized_var = serialize($var);
+        $serialized_var_len = strlen($serialized_var);
+
+        if ($flags & CACHE_IGNORE_SIZE > 0 && $serialized_var_len >= $this->getParam('soft_limit')) {
+            $app->logMsg(sprintf('Serialized variable (%s bytes) more than soft_limit (%s bytes).', $serialized_var_len, $this->getParam('soft_limit')), LOG_NOTICE, __FILE__, __LINE__);
+            return false;
+        }
+
+        if ($serialized_var_len >= $this->getParam('hard_limit')) {
+            $app->logMsg(sprintf('Serialized variable (%s bytes) more than hard_limit (%s bytes).', $serialized_var_len, $this->getParam('hard_limit')), LOG_NOTICE, __FILE__, __LINE__);
+            return false;
+        }
+
+        if (!isset($_SESSION['_session_cache'])) {
+            $_SESSION['_session_cache'] = array();
+        } else {
+            unset($_SESSION['_session_cache'][$key]);
+            // Continue to prune the cache if it's length is too long for the new variable to fit, but keep at least MIN_ITEMS at least.
+            while (strlen(serialize($_SESSION['_session_cache'])) + $serialized_var_len >= $this->getParam('soft_limit')
+            && sizeof($_SESSION['_session_cache']) >= $this->getParam('min_items')) {
+                array_shift($_SESSION['_session_cache']);
+            }
+        }
+        $_SESSION['_session_cache'][$key] =& $serialized_var;
+
+        if ($serialized_var_len >= 1024000) {
+            $app->logMsg(sprintf('Successfully cached oversized variable (%s bytes).', $serialized_var_len), LOG_DEBUG, __FILE__, __LINE__);
+        }
+
+        return true;
+    }
+
+    /**
+     * Retrives an object from the session cache and returns it unserialized.
+     * It also moves it to the top of the stack, which makes it such that the
+     * cache flushing mechanism of putCache deletes the oldest referenced items
+     * first.
+     *
+     * @param string $key  The key for the datum to retrieve.
+     *
+     * @return mixed          The requested datum, or false on failure.
+     */
+    function get($key)
+    {
+        if (!$this->getParam('enabled')) {
+            return false;
+        }
+
+        $key = md5($key);
+        if (isset($_SESSION['_session_cache'][$key])) {
+            // Move the accessed cached datum to the top of the stack. Maybe somebody knows a better way to do this?
+            $tmp =& $_SESSION['_session_cache'][$key];
+            unset($_SESSION['_session_cache'][$key]);
+            $_SESSION['_session_cache'][$key] =& $tmp;
+            // Return the unserialized datum.
+            return unserialize($_SESSION['_session_cache'][$key]);
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * Tells you if the object is cached.
+     *
+     * @param string $key  The key of the object to check.
+     *
+     * @return bool           The return from isset().
+     */
+    function exists($key)
+    {
+        if (!$this->getParam('enabled')) {
+            return false;
+        }
+
+        $key = md5($key);
+        return isset($_SESSION['_session_cache'][$key]);
+    }
+
+    /**
+     * Tells you if the object is cached.
+     *
+     * @param string $key  The key of the object to check.
+     *
+     * @return bool           The return from isset().
+     */
+    function delete($key)
+    {
+        $key = md5($key);
+        if (isset($_SESSION['_session_cache'][$key])) {
+            unset($_SESSION['_session_cache'][$key]);
+        }
+    }
+
+// END Cache
+}
+
+?>
Index: trunk/lib/Lock.inc.php
===================================================================
--- trunk/lib/Lock.inc.php	(revision 137)
+++ trunk/lib/Lock.inc.php	(revision 137)
@@ -0,0 +1,425 @@
+<?php
+/**
+ * RecordLock.inc.php
+ * code by strangecode :: www.strangecode.com :: this document contains copyrighted information
+ *
+ * The RecordLock class provides a system for locking abstract DB rows.
+ *
+ * @author  Quinn Comendant <quinn@strangecode.com>
+ * @version 2.1
+ */
+class RecordLock {
+
+    // Configuration of this object.
+    var $_params = array(
+        'timeout' => 600,
+        'auto_timeout' => 1800,
+        'error_url' => '/lock.php',
+        'db_table' => 'lock_tbl',
+        'create_table' => true, // Automatically create table and verify columns. Better set to false after site launch.
+    );
+
+    // Store lock data from DB.
+    var $data = array();
+
+    // Auth_SQL object from which to access a current user_id.
+    var $_auth;
+
+    /**
+     * This method enforces the singleton pattern for this class.
+     *
+     * @return  object  Reference to the global RecordLock object.
+     * @access  public
+     * @static
+     */
+    function &getInstance($auth_object)
+    {
+        static $instance = null;
+
+        if ($instance === null) {
+            $instance = new RecordLock($auth_object);
+        }
+
+        return $instance;
+    }
+
+    /**
+     * Constructor. Pass an Auth object on which to perform user lookups.
+     *
+     * @param mixed  $auth_object  An Auth_SQL or Auth_FILE object.
+     */
+    function RecordLock($auth_object)
+    {
+		$app =& App::getInstance();
+
+        if (!method_exists($auth_object, 'getVal') || !method_exists($auth_object, 'getUsername')) {
+            trigger_error('Constructor not provided a valid Auth_* object.', E_USER_ERROR);
+        }
+
+        $this->_auth = $auth_object;
+
+        // Get create tables config from global context.
+        if (!is_null($app->getParam('db_create_tables'))) {
+            $this->setParam(array('create_table' => $app->getParam('db_create_tables')));
+        }
+    }
+
+    /**
+     * Setup the database table for this class.
+     *
+     * @access  public
+     * @author  Quinn Comendant <quinn@strangecode.com>
+     * @since   26 Aug 2005 17:09:36
+     */
+    function initDB($recreate_db=false)
+    {
+		$app =& App::getInstance();
+		$db =& DB::getInstance();
+
+        static $_db_tested = false;
+
+        if ($recreate_db || !$_db_tested && $this->getParam('create_table')) {
+            if ($recreate_db) {
+                $db->query("DROP TABLE IF EXISTS " . $this->getParam('db_table'));
+                $app->logMsg(sprintf('Dropping and recreating table %s.', $this->getParam('db_table')), LOG_DEBUG, __FILE__, __LINE__);
+            }
+            $db->query("CREATE TABLE IF NOT EXISTS " . $this->getParam('db_table') . " (
+                lock_id int NOT NULL auto_increment,
+                record_table varchar(255) NOT NULL default '',
+                record_key varchar(255) NOT NULL default '',
+                record_val varchar(255) NOT NULL default '',
+                title varchar(255) NOT NULL default '',
+                set_by_admin_id smallint(11) NOT NULL default '0',
+                lock_datetime datetime NOT NULL default '0000-00-00 00:00:00',
+                PRIMARY KEY (lock_id),
+                KEY record_table (record_table),
+                KEY record_key (record_key),
+                KEY record_val (record_val)
+            )");
+
+            if (!$db->columnExists($this->getParam('db_table'), array(
+                'lock_id',
+                'record_table',
+                'record_key',
+                'record_val',
+                'title',
+                'set_by_admin_id',
+                'lock_datetime',
+            ), false, false)) {
+                $app->logMsg(sprintf('Database table %s has invalid columns. Please update this table manually.', $this->getParam('db_table')), LOG_ALERT, __FILE__, __LINE__);
+                trigger_error(sprintf('Database table %s has invalid columns. Please update this table manually.', $this->getParam('db_table')), E_USER_ERROR);
+            }
+        }
+        $_db_tested = true;
+    }
+
+    /**
+     * Set the params of this object.
+     *
+     * @param  array $params   Array of param keys and values to set.
+     */
+    function setParam($params=null)
+    {
+        if (isset($params) && is_array($params)) {
+            // Merge new parameters with old overriding only those passed.
+            $this->_params = array_merge($this->_params, $params);
+        }
+    }
+
+    /**
+     * Return the value of a parameter, if it exists.
+     *
+     * @access public
+     * @param string $param        Which parameter to return.
+     * @return mixed               Configured parameter value.
+     */
+    function getParam($param)
+    {
+		$app =& App::getInstance();
+    
+        if (isset($this->_params[$param])) {
+            return $this->_params[$param];
+        } else {
+            $app->logMsg(sprintf('Parameter is not set: %s', $param), LOG_NOTICE, __FILE__, __LINE__);
+            return null;
+        }
+    }
+
+    /**
+     * Select the lock to manipulate.
+     *
+     * @param mixed  $record_table_or_lock_id  The table containing the record to lock,
+     *                                         or a numeric lock_id.
+     * @param string $record_key  The key column for the record to lock.
+     * @param string $record_val  The value of the key column for the record to lock.
+     * @param string $title       A title to apply to the lock, for display purposes.
+     */
+    function select($record_table_or_lock_id, $record_key=null, $record_val=null)
+    {
+		$app =& App::getInstance();
+		$db =& DB::getInstance();
+
+        $this->initDB();
+
+        // Expire old locks.
+        $this->_auto_timeout();
+
+        if (is_numeric($record_table_or_lock_id) && !isset($record_key) && !isset($record_val)) {
+            // Get lock data by lock_id.
+            $qid = $db->query("
+                SELECT * FROM " . $this->getParam('db_table') . "
+                WHERE lock_id = '" . $db->escapeString($record_table_or_lock_id) . "'
+            ");
+        } else {
+            // Get lock data by record specs
+            $qid = $db->query("
+                SELECT * FROM " . $this->getParam('db_table') . "
+                WHERE record_table = '" . $db->escapeString($record_table_or_lock_id) . "'
+                AND record_key = '" . $db->escapeString($record_key) . "'
+                AND record_val = '" . $db->escapeString($record_val) . "'
+            ");
+        }
+        if ($this->data = mysql_fetch_assoc($qid)) {
+            $app->logMsg(sprintf('Selecting %slocked record: %s %s %s', ($this->data['set_by_admin_id'] == $this->_auth->getVal('user_id') ? 'self-' : ''), $record_table_or_lock_id, $record_key, $record_val), LOG_DEBUG, __FILE__, __LINE__);
+            /// FIX ME: What if admin set lock, but public user is current lock user?
+            $this->data['editor'] = $this->_auth->getUsername($this->data['set_by_admin_id']);
+            return true;
+        } else {
+            $app->logMsg(sprintf('No locked record: %s %s %s', $record_table_or_lock_id, $record_key, $record_val), LOG_DEBUG, __FILE__, __LINE__);
+            return false;
+        }
+    }
+
+    /**
+     * Returns true if the record we instantiated with is locked.
+     *
+     * @return bool            True if locked.
+     */
+    function isLocked()
+    {
+        return isset($this->data['lock_id']);
+    }
+
+    /**
+     * Returns the status of who set the lock. Use this to ignore locks set by
+     * the current user.
+     *
+     * @return bool            True if current user set the lock.
+     */
+    function isMine()
+    {
+		$db =& DB::getInstance();
+	
+        $this->initDB();
+
+        if (isset($this->data['lock_id'])) {
+            $qid = $db->query("SELECT * FROM " . $this->getParam('db_table') . " WHERE lock_id = '" . $db->escapeString($this->data['lock_id']) . "'");
+            if ($lock = mysql_fetch_assoc($qid)) {
+                return ($lock['set_by_admin_id'] == $this->_auth->getVal('user_id'));
+            } else {
+                return false;
+            }
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * Create a new lock for the specified table/key/value.
+     *
+     * @param string $record_table  The table containing the record to lock.
+     * @param string $record_key  The key column for the record to lock.
+     * @param string $record_val  The value of the key column for the record to lock.
+     * @param string $title       A title to apply to the lock, for display purposes.
+     *
+     * @return int            The id for the lock (mysql last insert id).
+     */
+    function set($record_table, $record_key, $record_val, $title='')
+    {
+		$db =& DB::getInstance();
+	
+        $this->initDB();
+
+        // Expire old locks.
+        $this->_auto_timeout();
+
+        // Remove previous locks if exist. Is this better than using a REPLACE INTO?
+        $db->query("
+            DELETE FROM " . $this->getParam('db_table') . "
+            WHERE record_table = '" . $db->escapeString($record_table) . "'
+            AND record_key = '" . $db->escapeString($record_key) . "'
+            AND record_val = '" . $db->escapeString($record_val) . "'
+        ");
+
+        // Set new lock.
+        $db->query("
+            INSERT INTO " . $this->getParam('db_table') . " (
+                record_table,
+                record_key,
+                record_val,
+                title,
+                set_by_admin_id,
+                lock_datetime
+            ) VALUES (
+                '" . $db->escapeString($record_table) . "',
+                '" . $db->escapeString($record_key) . "',
+                '" . $db->escapeString($record_val) . "',
+                '" . $db->escapeString($title) . "',
+                '" . $db->escapeString($this->_auth->getVal('user_id')) . "',
+                NOW()
+            )
+        ");
+        $lock_id = mysql_insert_id($db->getDBH());
+
+        // Must register this locked record as the current.
+        $this->select($lock_id);
+
+        return $lock_id;
+    }
+
+    /**
+     * Unlock the currently selected record.
+     */
+    function remove()
+    {
+		$app =& App::getInstance();
+		$db =& DB::getInstance();
+
+        $this->initDB();
+
+        // Expire old locks.
+        $this->_auto_timeout();
+
+        // Delete a specific lock.
+        $db->query("
+            DELETE FROM " . $this->getParam('db_table') . "
+            WHERE lock_id = '" . $db->escapeString($this->data['lock_id']) . "'
+        ");
+
+        $app->logMsg(sprintf('Removing lock: %s', $this->data['lock_id']), LOG_DEBUG, __FILE__, __LINE__);
+    }
+
+    /**
+     * Unlock all records, or all records for a specified user.
+     */
+    function removeAll($user_id=null)
+    {
+		$app =& App::getInstance();
+		$db =& DB::getInstance();
+
+        $this->initDB();
+
+        // Expire old locks.
+        $this->_auto_timeout();
+
+        if (isset($user_id)) {
+            // Delete specific user's locks.
+            $db->query("DELETE FROM " . $this->getParam('db_table') . " WHERE set_by_admin_id = '" . $db->escapeString($user_id) . "'");
+            $app->logMsg(sprintf('Record locks owned by %s %s have been deleted', $this->_auth->getVal('auth_name'), $this->_auth->getUsername($user_id)), LOG_DEBUG, __FILE__, __LINE__);
+        } else {
+            // Delete ALL locks.
+            $db->query("DELETE FROM " . $this->getParam('db_table') . "");
+            $app->logMsg(sprintf('All record locks deleted by %s %s', $this->_auth->getVal('auth_name'), $this->_auth->getVal('username')), LOG_DEBUG, __FILE__, __LINE__);
+        }
+    }
+
+    /**
+     * Delete's all locks that are older than auto_timeout.
+     */
+    function _auto_timeout()
+    {
+		$db =& DB::getInstance();
+	
+        static $_timeout_run = false;
+
+        $this->initDB();
+
+        if (!$_timeout_run) {
+            // Delete all old locks.
+            $db->query("
+                DELETE FROM " . $this->getParam('db_table') . "
+                WHERE DATE_ADD(lock_datetime, INTERVAL '" . $this->getParam('auto_timeout') . "' SECOND) < NOW()
+            ");
+            $_timeout_run = true;
+        }
+    }
+
+    /**
+     * Redirect to record lock error page.
+     */
+    function dieErrorPage()
+    {
+		$app =& App::getInstance();
+
+        $app->dieURL(sprintf('%s?lock_id=%s&boomerang=%s', $this->getParam('error_url'), $this->data['lock_id'], urlencode(absoluteMe())));
+    }
+
+    /**
+     * Print error page.
+     */
+    function printErrorHTML()
+    {
+		$app =& App::getInstance();
+
+        ?>
+        <form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
+        <?php $app->printHiddenSession() ?>
+        <input type="hidden" name="lock_id" value="<?php echo $this->getID(); ?>" />
+
+        <p><?php
+        printf(_("The record <strong>%s</strong> is currently being edited by <strong>%s</strong> (%d minutes elapsed). You cannot modify the record while it is locked by another user."),
+            $this->getTitle(),
+            $this->getEditor(),
+            date('i', $this->getSecondsElapsed() + 60)
+        );
+        ?></p>
+
+        <?php if ($this->getSecondsElapsed() > $this->getParam('timeout')) { ?>
+        <p><?php printf(_("You can forcibly unlock the record if you believe the editing session has expired. You might want to confirm with %s before doing this."), $this->getEditor()) ?></p>
+        <input type="submit" name="unlock" value="<?php echo _("Unlock"); ?>" />
+        <?php } ?>
+
+        <input type="submit" name="cancel" value="<?php echo _("Cancel"); ?>" />
+        </form>
+        <?php
+    }
+
+    /**
+     * Return lock_id of locked record.
+     */
+    function getID()
+    {
+        return $this->data['lock_id'];
+    }
+
+    /**
+     * Return title of locked record.
+     */
+    function getTitle()
+    {
+        return $this->data['title'];
+    }
+
+    /**
+     * Return administrator username for locked record.
+     */
+    function getEditor()
+    {
+        return $this->data['editor'];
+    }
+
+    /**
+     * Return total seconds since the record was locked.
+     */
+    function getSecondsElapsed()
+    {
+        if (isset($this->data['lock_datetime']) && $this->data['lock_datetime'] < time()) {
+            return time() - strtotime($this->data['lock_datetime']);
+        } else {
+            return 0;
+        }
+    }
+
+
+} // End of class.
+?>
Index: trunk/lib/RecordLock.inc.php
===================================================================
--- trunk/lib/RecordLock.inc.php	(revision 136)
+++ 	(revision )
@@ -1,425 +1,0 @@
-<?php
-/**
- * RecordLock.inc.php
- * code by strangecode :: www.strangecode.com :: this document contains copyrighted information
- *
- * The RecordLock class provides a system for locking abstract DB rows.
- *
- * @author  Quinn Comendant <quinn@strangecode.com>
- * @version 2.1
- */
-class RecordLock {
-
-    // Configuration of this object.
-    var $_params = array(
-        'timeout' => 600,
-        'auto_timeout' => 1800,
-        'error_url' => '/lock.php',
-        'db_table' => 'lock_tbl',
-        'create_table' => true, // Automatically create table and verify columns. Better set to false after site launch.
-    );
-
-    // Store lock data from DB.
-    var $data = array();
-
-    // Auth_SQL object from which to access a current user_id.
-    var $_auth;
-
-    /**
-     * This method enforces the singleton pattern for this class.
-     *
-     * @return  object  Reference to the global RecordLock object.
-     * @access  public
-     * @static
-     */
-    function &getInstance($auth_object)
-    {
-        static $instance = null;
-
-        if ($instance === null) {
-            $instance = new RecordLock($auth_object);
-        }
-
-        return $instance;
-    }
-
-    /**
-     * Constructor. Pass an Auth object on which to perform user lookups.
-     *
-     * @param mixed  $auth_object  An Auth_SQL or Auth_FILE object.
-     */
-    function RecordLock($auth_object)
-    {
-		$app =& App::getInstance();
-
-        if (!method_exists($auth_object, 'getVal') || !method_exists($auth_object, 'getUsername')) {
-            trigger_error('Constructor not provided a valid Auth_* object.', E_USER_ERROR);
-        }
-
-        $this->_auth = $auth_object;
-
-        // Get create tables config from global context.
-        if (!is_null($app->getParam('db_create_tables'))) {
-            $this->setParam(array('create_table' => $app->getParam('db_create_tables')));
-        }
-    }
-
-    /**
-     * Setup the database table for this class.
-     *
-     * @access  public
-     * @author  Quinn Comendant <quinn@strangecode.com>
-     * @since   26 Aug 2005 17:09:36
-     */
-    function initDB($recreate_db=false)
-    {
-		$app =& App::getInstance();
-		$db =& DB::getInstance();
-
-        static $_db_tested = false;
-
-        if ($recreate_db || !$_db_tested && $this->getParam('create_table')) {
-            if ($recreate_db) {
-                $db->query("DROP TABLE IF EXISTS " . $this->getParam('db_table'));
-                $app->logMsg(sprintf('Dropping and recreating table %s.', $this->getParam('db_table')), LOG_DEBUG, __FILE__, __LINE__);
-            }
-            $db->query("CREATE TABLE IF NOT EXISTS " . $this->getParam('db_table') . " (
-                lock_id int NOT NULL auto_increment,
-                record_table varchar(255) NOT NULL default '',
-                record_key varchar(255) NOT NULL default '',
-                record_val varchar(255) NOT NULL default '',
-                title varchar(255) NOT NULL default '',
-                set_by_admin_id smallint(11) NOT NULL default '0',
-                lock_datetime datetime NOT NULL default '0000-00-00 00:00:00',
-                PRIMARY KEY (lock_id),
-                KEY record_table (record_table),
-                KEY record_key (record_key),
-                KEY record_val (record_val)
-            )");
-
-            if (!$db->columnExists($this->getParam('db_table'), array(
-                'lock_id',
-                'record_table',
-                'record_key',
-                'record_val',
-                'title',
-                'set_by_admin_id',
-                'lock_datetime',
-            ), false, false)) {
-                $app->logMsg(sprintf('Database table %s has invalid columns. Please update this table manually.', $this->getParam('db_table')), LOG_ALERT, __FILE__, __LINE__);
-                trigger_error(sprintf('Database table %s has invalid columns. Please update this table manually.', $this->getParam('db_table')), E_USER_ERROR);
-            }
-        }
-        $_db_tested = true;
-    }
-
-    /**
-     * Set the params of this object.
-     *
-     * @param  array $params   Array of param keys and values to set.
-     */
-    function setParam($params=null)
-    {
-        if (isset($params) && is_array($params)) {
-            // Merge new parameters with old overriding only those passed.
-            $this->_params = array_merge($this->_params, $params);
-        }
-    }
-
-    /**
-     * Return the value of a parameter, if it exists.
-     *
-     * @access public
-     * @param string $param        Which parameter to return.
-     * @return mixed               Configured parameter value.
-     */
-    function getParam($param)
-    {
-		$app =& App::getInstance();
-    
-        if (isset($this->_params[$param])) {
-            return $this->_params[$param];
-        } else {
-            $app->logMsg(sprintf('Parameter is not set: %s', $param), LOG_NOTICE, __FILE__, __LINE__);
-            return null;
-        }
-    }
-
-    /**
-     * Select the lock to manipulate.
-     *
-     * @param mixed  $record_table_or_lock_id  The table containing the record to lock,
-     *                                         or a numeric lock_id.
-     * @param string $record_key  The key column for the record to lock.
-     * @param string $record_val  The value of the key column for the record to lock.
-     * @param string $title       A title to apply to the lock, for display purposes.
-     */
-    function select($record_table_or_lock_id, $record_key=null, $record_val=null)
-    {
-		$app =& App::getInstance();
-		$db =& DB::getInstance();
-
-        $this->initDB();
-
-        // Expire old locks.
-        $this->_auto_timeout();
-
-        if (is_numeric($record_table_or_lock_id) && !isset($record_key) && !isset($record_val)) {
-            // Get lock data by lock_id.
-            $qid = $db->query("
-                SELECT * FROM " . $this->getParam('db_table') . "
-                WHERE lock_id = '" . $db->escapeString($record_table_or_lock_id) . "'
-            ");
-        } else {
-            // Get lock data by record specs
-            $qid = $db->query("
-                SELECT * FROM " . $this->getParam('db_table') . "
-                WHERE record_table = '" . $db->escapeString($record_table_or_lock_id) . "'
-                AND record_key = '" . $db->escapeString($record_key) . "'
-                AND record_val = '" . $db->escapeString($record_val) . "'
-            ");
-        }
-        if ($this->data = mysql_fetch_assoc($qid)) {
-            $app->logMsg(sprintf('Selecting %slocked record: %s %s %s', ($this->data['set_by_admin_id'] == $this->_auth->getVal('user_id') ? 'self-' : ''), $record_table_or_lock_id, $record_key, $record_val), LOG_DEBUG, __FILE__, __LINE__);
-            /// FIX ME: What if admin set lock, but public user is current lock user?
-            $this->data['editor'] = $this->_auth->getUsername($this->data['set_by_admin_id']);
-            return true;
-        } else {
-            $app->logMsg(sprintf('No locked record: %s %s %s', $record_table_or_lock_id, $record_key, $record_val), LOG_DEBUG, __FILE__, __LINE__);
-            return false;
-        }
-    }
-
-    /**
-     * Returns true if the record we instantiated with is locked.
-     *
-     * @return bool            True if locked.
-     */
-    function isLocked()
-    {
-        return isset($this->data['lock_id']);
-    }
-
-    /**
-     * Returns the status of who set the lock. Use this to ignore locks set by
-     * the current user.
-     *
-     * @return bool            True if current user set the lock.
-     */
-    function isMine()
-    {
-		$db =& DB::getInstance();
-	
-        $this->initDB();
-
-        if (isset($this->data['lock_id'])) {
-            $qid = $db->query("SELECT * FROM " . $this->getParam('db_table') . " WHERE lock_id = '" . $db->escapeString($this->data['lock_id']) . "'");
-            if ($lock = mysql_fetch_assoc($qid)) {
-                return ($lock['set_by_admin_id'] == $this->_auth->getVal('user_id'));
-            } else {
-                return false;
-            }
-        } else {
-            return false;
-        }
-    }
-
-    /**
-     * Create a new lock for the specified table/key/value.
-     *
-     * @param string $record_table  The table containing the record to lock.
-     * @param string $record_key  The key column for the record to lock.
-     * @param string $record_val  The value of the key column for the record to lock.
-     * @param string $title       A title to apply to the lock, for display purposes.
-     *
-     * @return int            The id for the lock (mysql last insert id).
-     */
-    function set($record_table, $record_key, $record_val, $title='')
-    {
-		$db =& DB::getInstance();
-	
-        $this->initDB();
-
-        // Expire old locks.
-        $this->_auto_timeout();
-
-        // Remove previous locks if exist. Is this better than using a REPLACE INTO?
-        $db->query("
-            DELETE FROM " . $this->getParam('db_table') . "
-            WHERE record_table = '" . $db->escapeString($record_table) . "'
-            AND record_key = '" . $db->escapeString($record_key) . "'
-            AND record_val = '" . $db->escapeString($record_val) . "'
-        ");
-
-        // Set new lock.
-        $db->query("
-            INSERT INTO " . $this->getParam('db_table') . " (
-                record_table,
-                record_key,
-                record_val,
-                title,
-                set_by_admin_id,
-                lock_datetime
-            ) VALUES (
-                '" . $db->escapeString($record_table) . "',
-                '" . $db->escapeString($record_key) . "',
-                '" . $db->escapeString($record_val) . "',
-                '" . $db->escapeString($title) . "',
-                '" . $db->escapeString($this->_auth->getVal('user_id')) . "',
-                NOW()
-            )
-        ");
-        $lock_id = mysql_insert_id($db->getDBH());
-
-        // Must register this locked record as the current.
-        $this->select($lock_id);
-
-        return $lock_id;
-    }
-
-    /**
-     * Unlock the currently selected record.
-     */
-    function remove()
-    {
-		$app =& App::getInstance();
-		$db =& DB::getInstance();
-
-        $this->initDB();
-
-        // Expire old locks.
-        $this->_auto_timeout();
-
-        // Delete a specific lock.
-        $db->query("
-            DELETE FROM " . $this->getParam('db_table') . "
-            WHERE lock_id = '" . $db->escapeString($this->data['lock_id']) . "'
-        ");
-
-        $app->logMsg(sprintf('Removing lock: %s', $this->data['lock_id']), LOG_DEBUG, __FILE__, __LINE__);
-    }
-
-    /**
-     * Unlock all records, or all records for a specified user.
-     */
-    function removeAll($user_id=null)
-    {
-		$app =& App::getInstance();
-		$db =& DB::getInstance();
-
-        $this->initDB();
-
-        // Expire old locks.
-        $this->_auto_timeout();
-
-        if (isset($user_id)) {
-            // Delete specific user's locks.
-            $db->query("DELETE FROM " . $this->getParam('db_table') . " WHERE set_by_admin_id = '" . $db->escapeString($user_id) . "'");
-            $app->logMsg(sprintf('Record locks owned by %s %s have been deleted', $this->_auth->getVal('auth_name'), $this->_auth->getUsername($user_id)), LOG_DEBUG, __FILE__, __LINE__);
-        } else {
-            // Delete ALL locks.
-            $db->query("DELETE FROM " . $this->getParam('db_table') . "");
-            $app->logMsg(sprintf('All record locks deleted by %s %s', $this->_auth->getVal('auth_name'), $this->_auth->getVal('username')), LOG_DEBUG, __FILE__, __LINE__);
-        }
-    }
-
-    /**
-     * Delete's all locks that are older than auto_timeout.
-     */
-    function _auto_timeout()
-    {
-		$db =& DB::getInstance();
-	
-        static $_timeout_run = false;
-
-        $this->initDB();
-
-        if (!$_timeout_run) {
-            // Delete all old locks.
-            $db->query("
-                DELETE FROM " . $this->getParam('db_table') . "
-                WHERE DATE_ADD(lock_datetime, INTERVAL '" . $this->getParam('auto_timeout') . "' SECOND) < NOW()
-            ");
-            $_timeout_run = true;
-        }
-    }
-
-    /**
-     * Redirect to record lock error page.
-     */
-    function dieErrorPage()
-    {
-		$app =& App::getInstance();
-
-        $app->dieURL(sprintf('%s?lock_id=%s&boomerang=%s', $this->getParam('error_url'), $this->data['lock_id'], urlencode(absoluteMe())));
-    }
-
-    /**
-     * Print error page.
-     */
-    function printErrorHTML()
-    {
-		$app =& App::getInstance();
-
-        ?>
-        <form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
-        <?php $app->printHiddenSession() ?>
-        <input type="hidden" name="lock_id" value="<?php echo $this->getID(); ?>" />
-
-        <p><?php
-        printf(_("The record <strong>%s</strong> is currently being edited by <strong>%s</strong> (%d minutes elapsed). You cannot modify the record while it is locked by another user."),
-            $this->getTitle(),
-            $this->getEditor(),
-            date('i', $this->getSecondsElapsed() + 60)
-        );
-        ?></p>
-
-        <?php if ($this->getSecondsElapsed() > $this->getParam('timeout')) { ?>
-        <p><?php printf(_("You can forcibly unlock the record if you believe the editing session has expired. You might want to confirm with %s before doing this."), $this->getEditor()) ?></p>
-        <input type="submit" name="unlock" value="<?php echo _("Unlock"); ?>" />
-        <?php } ?>
-
-        <input type="submit" name="cancel" value="<?php echo _("Cancel"); ?>" />
-        </form>
-        <?php
-    }
-
-    /**
-     * Return lock_id of locked record.
-     */
-    function getID()
-    {
-        return $this->data['lock_id'];
-    }
-
-    /**
-     * Return title of locked record.
-     */
-    function getTitle()
-    {
-        return $this->data['title'];
-    }
-
-    /**
-     * Return administrator username for locked record.
-     */
-    function getEditor()
-    {
-        return $this->data['editor'];
-    }
-
-    /**
-     * Return total seconds since the record was locked.
-     */
-    function getSecondsElapsed()
-    {
-        if (isset($this->data['lock_datetime']) && $this->data['lock_datetime'] < time()) {
-            return time() - strtotime($this->data['lock_datetime']);
-        } else {
-            return 0;
-        }
-    }
-
-
-} // End of class.
-?>
Index: trunk/lib/RecordVersion.inc.php
===================================================================
--- trunk/lib/RecordVersion.inc.php	(revision 136)
+++ 	(revision )
@@ -1,442 +1,0 @@
-<?php
-/**
- * RecordVersion.inc.php
- * code by strangecode :: www.strangecode.com :: this document contains copyrighted information
- *
- * The RecordVersion class provides a system for saving, reviewing, and
- * restoring versions of a record of any DB table. All the data in the record is
- * serialized, compressed, and saved in a blob in the version_tbl. Restoring a
- * version simply does a REPLACE INTO of the data. It is very simple, and works
- * with multiple database tables, but the drawback is that relationships for
- * a record cannot be retained. For example, an article from an article_tbl can
- * be saved, but not categories associated to the record in a category_article_tbl.
- * The restored article will simple retain the relationships that the previous
- * current article had.
- *
- * @author  Quinn Comendant <quinn@strangecode.com>
- * @version 2.1
- */
-class RecordVersion {
-
-    // Configuration of this object.
-    var $_params = array(
-        'max_qty' => 100, // Never have more than this many versions of each record.
-        'min_qty' => 25, // Keep at least this many versions of each record.
-        'min_days' => 7, // Keep ALL versions within this many days, even if MORE than min_qty.
-        'db_table' => 'version_tbl',
-        'create_table' => true, // Automatically create table and verify columns. Better set to false after site launch.
-        'db_schema_strict' => true, // If true, makes an exact comparison of saved vs. live table schemas. If false, just checks that the saved columns are available.
-    );
-
-    // Auth_SQL object from which to access a current user_id.
-    var $_auth;
-
-    /**
-     * This method enforces the singleton pattern for this class.
-     *
-     * @return  object  Reference to the global RecordLock object.
-     * @access  public
-     * @static
-     */
-    function &getInstance($auth_object)
-    {
-        static $instance = null;
-
-        if ($instance === null) {
-            $instance = new RecordVersion($auth_object);
-        }
-
-        return $instance;
-    }
-
-    /**
-     * Constructor. Pass an Auth object on which to perform user lookups.
-     *
-     * @param mixed  $auth_object  An Auth_SQL object.
-     */
-    function RecordVersion($auth_object)
-    {
-		$app =& App::getInstance();
-
-        if (!method_exists($auth_object, 'getVal') || !method_exists($auth_object, 'getUsername')) {
-            trigger_error('Constructor not provided a valid Auth_* object.', E_USER_ERROR);
-        }
-
-        $this->_auth = $auth_object;
-
-        // Get create tables config from global context.
-        if (!is_null($app->getParam('db_create_tables'))) {
-            $this->setParam(array('create_table' => $app->getParam('db_create_tables')));
-        }
-    }
-
-    /**
-     * Setup the database table for this class.
-     *
-     * @access  public
-     * @author  Quinn Comendant <quinn@strangecode.com>
-     * @since   26 Aug 2005 17:09:36
-     */
-    function initDB($recreate_db=false)
-    {
-		$app =& App::getInstance();
-		$db =& DB::getInstance();
-
-        static $_db_tested = false;
-
-        if ($recreate_db || !$_db_tested && $this->getParam('create_table')) {
-            if ($recreate_db) {
-                $db->query("DROP TABLE IF EXISTS " . $this->getParam('db_table'));
-                $app->logMsg(sprintf('Dropping and recreating table %s.', $this->getParam('db_table')), LOG_DEBUG, __FILE__, __LINE__);
-            }
-            $db->query("CREATE TABLE IF NOT EXISTS " . $this->getParam('db_table') . " (
-                version_id int NOT NULL auto_increment,
-                record_table varchar(255) NOT NULL default '',
-                record_key varchar(255) NOT NULL default '',
-                record_val varchar(255) NOT NULL default '',
-                version_data mediumblob NOT NULL,
-                version_title varchar(255) NOT NULL default '',
-                version_notes varchar(255) NOT NULL default '',
-                saved_by_admin_id smallint(11) NOT NULL default '0',
-                version_datetime datetime NOT NULL default '0000-00-00 00:00:00',
-                PRIMARY KEY (version_id),
-                KEY record_table (record_table),
-                KEY record_key (record_key),
-                KEY record_val (record_val)
-            )");
-
-            if (!$db->columnExists($this->getParam('db_table'), array(
-                'version_id',
-                'record_table',
-                'record_key',
-                'record_val',
-                'version_data',
-                'version_title',
-                'version_notes',
-                'saved_by_admin_id',
-                'version_datetime',
-            ), false, false)) {
-                $app->logMsg(sprintf('Database table %s has invalid columns. Please update this table manually.', $this->getParam('db_table')), LOG_ALERT, __FILE__, __LINE__);
-                trigger_error(sprintf('Database table %s has invalid columns. Please update this table manually.', $this->getParam('db_table')), E_USER_ERROR);
-            }
-        }
-        $_db_tested = true;
-    }
-
-    /**
-     * Set the params of this object.
-     *
-     * @param  array $params   Array of param keys and values to set.
-     */
-    function setParam($params=null)
-    {
-        if (isset($params) && is_array($params)) {
-            // Merge new parameters with old overriding only those passed.
-            $this->_params = array_merge($this->_params, $params);
-        }
-    }
-
-    /**
-     * Return the value of a parameter, if it exists.
-     *
-     * @access public
-     * @param string $param        Which parameter to return.
-     * @return mixed               Configured parameter value.
-     */
-    function getParam($param)
-    {
-		$app =& App::getInstance();
-    
-        if (isset($this->_params[$param])) {
-            return $this->_params[$param];
-        } else {
-            $app->logMsg(sprintf('Parameter is not set: %s', $param), LOG_NOTICE, __FILE__, __LINE__);
-            return null;
-        }
-    }
-
-    /**
-     * Saves a version of the current record into the version table.
-     *
-     * @param string $record_table  The table containing the record.
-     * @param string $record_key    The key column for the record.
-     * @param string $record_val    The value of the key column for the record.
-     * @param string $title         The title of this record. Only used for human presentation.
-     *
-     * @return int                  The id for the version (mysql last insert id).
-     */
-    function create($record_table, $record_key, $record_val, $title='', $notes='')
-    {
-		$app =& App::getInstance();
-		$db =& DB::getInstance();
-
-        $this->initDB();
-
-        // Get current record.
-        if (!$record = $this->getCurrent($record_table, $record_key, $record_val)) {
-            $app->logMsg(sprintf('Could not create %s version, record not found: %s, %s, %s.', $title, $record_table, $record_key, $record_val), LOG_ERR, __FILE__, __LINE__);
-            return false;
-        }
-
-        // Clean-up old versions.
-        $this->deleteOld($record_table, $record_key, $record_val);
-
-        // Save as new version.
-        $db->query("
-            INSERT INTO " . $this->getParam('db_table') . " (
-                record_table,
-                record_key,
-                record_val,
-                version_data,
-                version_title,
-                version_notes,
-                saved_by_admin_id,
-                version_datetime
-            ) VALUES (
-                '" . $db->escapeString($record_table) . "',
-                '" . $db->escapeString($record_key) . "',
-                '" . $db->escapeString($record_val) . "',
-                '" . $db->escapeString(gzcompress(serialize($record), 9)) . "',
-                '" . $db->escapeString($title) . "',
-                '" . $db->escapeString($notes) . "',
-                '" . $db->escapeString($this->_auth->getVal('user_id')) . "',
-                NOW()
-            )
-        ");
-
-        return mysql_insert_id($db->getDBH());
-    }
-
-    /**
-     * Copy a version back into it's original table.
-     *
-     * @param string $version_id    The id of the version to restore.
-     *
-     * @return int                  The id for the version (mysql last insert id).
-     */
-    function restore($version_id)
-    {
-		$app =& App::getInstance();
-		$db =& DB::getInstance();
-
-        $this->initDB();
-
-        // Get version data.
-        $qid = $db->query("
-            SELECT * FROM " . $this->getParam('db_table') . "
-            WHERE version_id = '" . $db->escapeString($version_id) . "'
-        ");
-        if (!$record = mysql_fetch_assoc($qid)) {
-            $app->raiseMsg(sprintf(_("Version ID %s%s not found."), $version_id, (empty($record['version_title']) ? '' : ' (' . $record['version_title'] . ')')), MSG_WARNING, __FILE__, __LINE__);
-            $app->logMsg(sprintf(_("Version ID %s%s not found."), $version_id, (empty($record['version_title']) ? '' : ' (' . $record['version_title'] . ')')), LOG_WARNING, __FILE__, __LINE__);
-            return false;
-        }
-        $data = unserialize(gzuncompress($record['version_data']));
-
-        // Ensure saved db columns match current table schema.
-        if (!$db->columnExists($record['record_table'], array_keys($data), $this->getParam('db_schema_strict'))) {
-            $app->raiseMsg(sprintf(_("Version ID %s%s is not compatible with the current database table."), $version_id, (empty($record['version_title']) ? '' : ' (' . $record['version_title'] . ')')), MSG_ERR, __FILE__, __LINE__);
-            $app->logMsg(sprintf(_("Version ID %s%s restoration failed, DB schema does not match for table %s."), $version_id, (empty($record['version_title']) ? '' : ' (' . $record['version_title'] . ')'), $record['record_table']), LOG_ALERT, __FILE__, __LINE__);
-            return false;
-        }
-
-        // SQLize the keys of the specified versioned record.
-        $replace_keys = join(",\n", array_map(array($db, 'escapeString'), array_keys($data)));
-
-        // SQLize the keys of the values of the specified versioned record. (These are more complex because we need to account for SQL null values.)
-        $replace_values = '';
-        $comma = '';
-        foreach ($data as $v) {
-            $replace_values .= is_null($v) ? "$comma\nNULL" : "$comma\n'" . $db->escapeString($v) . "'";
-            $comma = ',';
-        }
-
-        // Replace current record with specified versioned record.
-        $db->query("
-            REPLACE INTO " . $record['record_table'] . " (
-                $replace_keys
-            ) VALUES (
-                $replace_values
-            )
-        ");
-
-        return $record;
-    }
-
-    /**
-     * Version garbage collection. Deletes versions older than min_days
-     * when quantity of versions exceeds min_qty. If quantity
-     * exceeds 100 within min_days, the oldest are deleted to bring the
-     * quantity back down to min_qty.
-     *
-     * @param string $record_table  The table containing the record.
-     * @param string $record_key    The key column for the record.
-     * @param string $record_val    The value of the key column for the record.
-     *
-     * @return mixed                Array of versions, or false if none.
-     */
-    function deleteOld($record_table, $record_key, $record_val)
-    {
-		$db =& DB::getInstance();
-	
-        $this->initDB();
-
-        // Get total number of versions for this record.
-        $qid = $db->query("
-            SELECT COUNT(*) FROM " . $this->getParam('db_table') . "
-            WHERE record_table = '" . $db->escapeString($record_table) . "'
-            AND record_key = '" . $db->escapeString($record_key) . "'
-            AND record_val = '" . $db->escapeString($record_val) . "'
-        ");
-        list($v_count) = mysql_fetch_row($qid);
-
-        if ($v_count > $this->getParam('min_qty')) {
-            if ($v_count > $this->getParam('max_qty')) {
-                // To prevent a record bomb, limit max number of versions to max_qty.
-                // First query for oldest records, selecting enough to bring total number down to min_qty.
-                $qid = $db->query("
-                    SELECT version_id FROM " . $this->getParam('db_table') . "
-                    WHERE record_table = '" . $db->escapeString($record_table) . "'
-                    AND record_key = '" . $db->escapeString($record_key) . "'
-                    AND record_val = '" . $db->escapeString($record_val) . "'
-                    ORDER BY version_datetime ASC
-                    LIMIT " . ($v_count - $this->getParam('min_qty')) . "
-                ");
-                while (list($old_id) = mysql_fetch_row($qid)) {
-                    $old_versions[] = $old_id;
-                }
-                $db->query("
-                    DELETE FROM " . $this->getParam('db_table') . "
-                    WHERE version_id IN ('" . join("','", $old_versions) . "')
-                ");
-            } else {
-                // Delete versions older than min_days, while still keeping min_qty.
-                $qid = $db->query("
-                    SELECT version_id FROM " . $this->getParam('db_table') . "
-                    WHERE record_table = '" . $db->escapeString($record_table) . "'
-                    AND record_key = '" . $db->escapeString($record_key) . "'
-                    AND record_val = '" . $db->escapeString($record_val) . "'
-                    AND DATE_ADD(version_datetime, INTERVAL '" . $this->getParam('min_days') . "' DAY) < NOW()
-                    ORDER BY version_datetime ASC
-                    LIMIT " . ($v_count - $this->getParam('min_qty')) . "
-                ");
-                while (list($old_id) = mysql_fetch_row($qid)) {
-                    $old_versions[] = $old_id;
-                }
-                if (sizeof($old_versions) > 0) {
-                    $db->query("
-                        DELETE FROM " . $this->getParam('db_table') . "
-                        WHERE version_id IN ('" . join("','", $old_versions) . "')
-                    ");
-                }
-            }
-        }
-    }
-
-    /**
-     * Get a list of versions of specified record.
-     *
-     * @param string $record_table  The table containing the record.
-     * @param string $record_key    The key column for the record.
-     * @param string $record_val    The value of the key column for the record.
-     *
-     * @return mixed                Array of versions, or false if none.
-     */
-    function getList($record_table, $record_key, $record_val)
-    {
-		$db =& DB::getInstance();
-	
-        $this->initDB();
-
-        // Get versions of this record.
-        $qid = $db->query("
-            SELECT version_id, saved_by_admin_id, version_datetime, version_title
-            FROM " . $this->getParam('db_table') . "
-            WHERE record_table = '" . $db->escapeString($record_table) . "'
-            AND record_key = '" . $db->escapeString($record_key) . "'
-            AND record_val = '" . $db->escapeString($record_val) . "'
-            ORDER BY version_datetime DESC
-        ");
-        $versions = array();
-        while ($row = mysql_fetch_assoc($qid)) {
-            // Get admin usernames.
-            $row['editor'] = $this->_auth->getVal('auth_type') . ' ' . $this->_auth->getUsername($row['saved_by_admin_id']);
-            $versions[] = $row;
-        }
-        return $versions;
-    }
-
-    /**
-     * Get the version record for a specified version id.
-     *
-     * @param string $version_id    The id of the version to restore.
-     *
-     * @return mixed                Array of data saved in version, or false if none.
-     */
-    function getVerson($version_id)
-    {
-		$db =& DB::getInstance();
-	
-        $this->initDB();
-
-        // Get version data.
-        $qid = $db->query("
-            SELECT * FROM " . $this->getParam('db_table') . "
-            WHERE version_id = '" . $db->escapeString($version_id) . "'
-        ");
-        return mysql_fetch_assoc($qid);
-    }
-
-    /**
-     * Get the data stored for a specified version id.
-     *
-     * @param string $version_id    The id of the version to restore.
-     *
-     * @return mixed                Array of data saved in version, or false if none.
-     */
-    function getData($version_id)
-    {
-		$db =& DB::getInstance();
-	
-        $this->initDB();
-
-        // Get version data.
-        $qid = $db->query("
-            SELECT * FROM " . $this->getParam('db_table') . "
-            WHERE version_id = '" . $db->escapeString($version_id) . "'
-        ");
-        $record = mysql_fetch_assoc($qid);
-        if (isset($record['version_data'])) {
-            return unserialize(gzuncompress($record['version_data']));
-        } else {
-            return false;
-        }
-    }
-
-    /**
-     * Get the current record data from the original table.
-     *
-     * @param string $version_id    The id of the version to restore.
-     *
-     * @return mixed                Array of data saved in version, or false if none.
-     */
-    function getCurrent($record_table, $record_key, $record_val)
-    {
-		$db =& DB::getInstance();
-	
-        $this->initDB();
-
-        $qid = $db->query("
-            SELECT * FROM " . $db->escapeString($record_table) . "
-            WHERE " . $db->escapeString($record_key) . " = '" . $db->escapeString($record_val) . "'
-        ");
-        if ($record = mysql_fetch_assoc($qid)) {
-            return $record;
-        } else {
-            return false;
-        }
-    }
-
-
-} // End of class.
-?>
Index: trunk/lib/SessionCache.inc.php
===================================================================
--- trunk/lib/SessionCache.inc.php	(revision 136)
+++ 	(revision )
@@ -1,203 +1,0 @@
-<?php
-/**
- * Cache.inc.php
- * code by strangecode :: www.strangecode.com :: this document contains copyrighted information
- *
- * Provides an API for storing a limited amount of data
- * intended to have a short lifetime in a user's session.
- *
- * @author  Quinn Comendant <quinn@strangecode.com>
- * @version 2.1
- * @since   2001
- */
- 
-// Flags.
-define('CACHE_IGNORE_SIZE', 1);
-
-class Cache {
-
-    var $_params = array(
-        'enabled' => true,
-        'soft_limit' => 204800,
-        'hard_limit' => 4194304,
-        'min_items' => 3,
-    );
-
-    /**
-     * This method enforces the singleton pattern for this class.
-     *
-     * @return  object  Reference to the global Cache object.
-     * @access  public
-     * @static
-     */
-    function &getInstance()
-    {
-        static $instance = null;
-
-        if ($instance === null) {
-            $instance = new Cache();
-        }
-
-        return $instance;
-    }
-
-    /**
-     * Set (or overwrite existing) parameters by passing an array of new parameters.
-     *
-     * @access public
-     * @param  array    $params     Array of parameters (key => val pairs).
-     */
-    function setParam($params)
-    {
-		$app =& App::getInstance();
-
-        if (isset($params) && is_array($params)) {
-            // Merge new parameters with old overriding only those passed.
-            $this->_params = array_merge($this->_params, $params);
-        } else {
-            $app->logMsg(sprintf('Parameters are not an array: %s', $params), LOG_ERR, __FILE__, __LINE__);
-        }
-    }
-
-    /**
-     * Return the value of a parameter, if it exists.
-     *
-     * @access public
-     * @param string $param        Which parameter to return.
-     * @return mixed               Configured parameter value.
-     */
-    function getParam($param)
-    {
-		$app =& App::getInstance();
-    
-        if (isset($this->_params[$param])) {
-            return $this->_params[$param];
-        } else {
-            $app->logMsg(sprintf('Parameter is not set: %s', $param), LOG_NOTICE, __FILE__, __LINE__);
-            return null;
-        }
-    }
-
-    /**
-     * Stores a new variable in the session cache. The $key is is md5'ed
-     * because if a variable id is a very large integer, the array_shift function
-     * will reset the key to the next largest int key. Weird behavior I can't
-     * understand. $session_cache[32341234123] will become $session_cache[0]
-     * for example. Usage warning: if the variable is too big to fit, or is
-     * old and discarded, you must provide alternative ways of accessing the data.
-     *
-     * @param str   $key        An identifier for the cached object.
-     * @param mixed $var          The var to store in the session cache.
-     * @param bool  $flags      If we have something really big that we
-     *                            still want to cache, setting this to
-     *                            CACHE_IGNORE_SIZE allows this.
-     *
-     * @return bool               True on success, false otherwise.
-     */
-    function set($key, $var, $flags=0)
-    {
-		$app =& App::getInstance();
-
-        if (!$this->getParam('enabled')) {
-            $app->logMsg(sprintf('Cache not enabled, not saving data.', null), LOG_DEBUG, __FILE__, __LINE__);
-            return false;
-        }
-
-        $key = md5($key);
-        $serialized_var = serialize($var);
-        $serialized_var_len = strlen($serialized_var);
-
-        if ($flags & CACHE_IGNORE_SIZE > 0 && $serialized_var_len >= $this->getParam('soft_limit')) {
-            $app->logMsg(sprintf('Serialized variable (%s bytes) more than soft_limit (%s bytes).', $serialized_var_len, $this->getParam('soft_limit')), LOG_NOTICE, __FILE__, __LINE__);
-            return false;
-        }
-
-        if ($serialized_var_len >= $this->getParam('hard_limit')) {
-            $app->logMsg(sprintf('Serialized variable (%s bytes) more than hard_limit (%s bytes).', $serialized_var_len, $this->getParam('hard_limit')), LOG_NOTICE, __FILE__, __LINE__);
-            return false;
-        }
-
-        if (!isset($_SESSION['_session_cache'])) {
-            $_SESSION['_session_cache'] = array();
-        } else {
-            unset($_SESSION['_session_cache'][$key]);
-            // Continue to prune the cache if it's length is too long for the new variable to fit, but keep at least MIN_ITEMS at least.
-            while (strlen(serialize($_SESSION['_session_cache'])) + $serialized_var_len >= $this->getParam('soft_limit')
-            && sizeof($_SESSION['_session_cache']) >= $this->getParam('min_items')) {
-                array_shift($_SESSION['_session_cache']);
-            }
-        }
-        $_SESSION['_session_cache'][$key] =& $serialized_var;
-
-        if ($serialized_var_len >= 1024000) {
-            $app->logMsg(sprintf('Successfully cached oversized variable (%s bytes).', $serialized_var_len), LOG_DEBUG, __FILE__, __LINE__);
-        }
-
-        return true;
-    }
-
-    /**
-     * Retrives an object from the session cache and returns it unserialized.
-     * It also moves it to the top of the stack, which makes it such that the
-     * cache flushing mechanism of putCache deletes the oldest referenced items
-     * first.
-     *
-     * @param string $key  The key for the datum to retrieve.
-     *
-     * @return mixed          The requested datum, or false on failure.
-     */
-    function get($key)
-    {
-        if (!$this->getParam('enabled')) {
-            return false;
-        }
-
-        $key = md5($key);
-        if (isset($_SESSION['_session_cache'][$key])) {
-            // Move the accessed cached datum to the top of the stack. Maybe somebody knows a better way to do this?
-            $tmp =& $_SESSION['_session_cache'][$key];
-            unset($_SESSION['_session_cache'][$key]);
-            $_SESSION['_session_cache'][$key] =& $tmp;
-            // Return the unserialized datum.
-            return unserialize($_SESSION['_session_cache'][$key]);
-        } else {
-            return false;
-        }
-    }
-
-    /**
-     * Tells you if the object is cached.
-     *
-     * @param string $key  The key of the object to check.
-     *
-     * @return bool           The return from isset().
-     */
-    function exists($key)
-    {
-        if (!$this->getParam('enabled')) {
-            return false;
-        }
-
-        $key = md5($key);
-        return isset($_SESSION['_session_cache'][$key]);
-    }
-
-    /**
-     * Tells you if the object is cached.
-     *
-     * @param string $key  The key of the object to check.
-     *
-     * @return bool           The return from isset().
-     */
-    function delete($key)
-    {
-        $key = md5($key);
-        if (isset($_SESSION['_session_cache'][$key])) {
-            unset($_SESSION['_session_cache'][$key]);
-        }
-    }
-
-// END Cache
-}
-
-?>
Index: trunk/lib/Version.inc.php
===================================================================
--- trunk/lib/Version.inc.php	(revision 137)
+++ trunk/lib/Version.inc.php	(revision 137)
@@ -0,0 +1,442 @@
+<?php
+/**
+ * Version.inc.php
+ * code by strangecode :: www.strangecode.com :: this document contains copyrighted information
+ *
+ * The Version class provides a system for saving, reviewing, and
+ * restoring versions of a record of any DB table. All the data in the record is
+ * serialized, compressed, and saved in a blob in the version_tbl. Restoring a
+ * version simply does a REPLACE INTO of the data. It is very simple, and works
+ * with multiple database tables, but the drawback is that relationships for
+ * a record cannot be retained. For example, an article from an article_tbl can
+ * be saved, but not categories associated to the record in a category_article_tbl.
+ * The restored article will simple retain the relationships that the previous
+ * current article had.
+ *
+ * @author  Quinn Comendant <quinn@strangecode.com>
+ * @version 2.1
+ */
+class Version {
+
+    // Configuration of this object.
+    var $_params = array(
+        'max_qty' => 100, // Never have more than this many versions of each record.
+        'min_qty' => 25, // Keep at least this many versions of each record.
+        'min_days' => 7, // Keep ALL versions within this many days, even if MORE than min_qty.
+        'db_table' => 'version_tbl',
+        'create_table' => true, // Automatically create table and verify columns. Better set to false after site launch.
+        'db_schema_strict' => true, // If true, makes an exact comparison of saved vs. live table schemas. If false, just checks that the saved columns are available.
+    );
+
+    // Auth_SQL object from which to access a current user_id.
+    var $_auth;
+
+    /**
+     * This method enforces the singleton pattern for this class.
+     *
+     * @return  object  Reference to the global RecordLock object.
+     * @access  public
+     * @static
+     */
+    function &getInstance($auth_object)
+    {
+        static $instance = null;
+
+        if ($instance === null) {
+            $instance = new Version($auth_object);
+        }
+
+        return $instance;
+    }
+
+    /**
+     * Constructor. Pass an Auth object on which to perform user lookups.
+     *
+     * @param mixed  $auth_object  An Auth_SQL object.
+     */
+    function Version($auth_object)
+    {
+		$app =& App::getInstance();
+
+        if (!method_exists($auth_object, 'getVal') || !method_exists($auth_object, 'getUsername')) {
+            trigger_error('Constructor not provided a valid Auth_* object.', E_USER_ERROR);
+        }
+
+        $this->_auth = $auth_object;
+
+        // Get create tables config from global context.
+        if (!is_null($app->getParam('db_create_tables'))) {
+            $this->setParam(array('create_table' => $app->getParam('db_create_tables')));
+        }
+    }
+
+    /**
+     * Setup the database table for this class.
+     *
+     * @access  public
+     * @author  Quinn Comendant <quinn@strangecode.com>
+     * @since   26 Aug 2005 17:09:36
+     */
+    function initDB($recreate_db=false)
+    {
+		$app =& App::getInstance();
+		$db =& DB::getInstance();
+
+        static $_db_tested = false;
+
+        if ($recreate_db || !$_db_tested && $this->getParam('create_table')) {
+            if ($recreate_db) {
+                $db->query("DROP TABLE IF EXISTS " . $this->getParam('db_table'));
+                $app->logMsg(sprintf('Dropping and recreating table %s.', $this->getParam('db_table')), LOG_DEBUG, __FILE__, __LINE__);
+            }
+            $db->query("CREATE TABLE IF NOT EXISTS " . $this->getParam('db_table') . " (
+                version_id int NOT NULL auto_increment,
+                record_table varchar(255) NOT NULL default '',
+                record_key varchar(255) NOT NULL default '',
+                record_val varchar(255) NOT NULL default '',
+                version_data mediumblob NOT NULL,
+                version_title varchar(255) NOT NULL default '',
+                version_notes varchar(255) NOT NULL default '',
+                saved_by_admin_id smallint(11) NOT NULL default '0',
+                version_datetime datetime NOT NULL default '0000-00-00 00:00:00',
+                PRIMARY KEY (version_id),
+                KEY record_table (record_table),
+                KEY record_key (record_key),
+                KEY record_val (record_val)
+            )");
+
+            if (!$db->columnExists($this->getParam('db_table'), array(
+                'version_id',
+                'record_table',
+                'record_key',
+                'record_val',
+                'version_data',
+                'version_title',
+                'version_notes',
+                'saved_by_admin_id',
+                'version_datetime',
+            ), false, false)) {
+                $app->logMsg(sprintf('Database table %s has invalid columns. Please update this table manually.', $this->getParam('db_table')), LOG_ALERT, __FILE__, __LINE__);
+                trigger_error(sprintf('Database table %s has invalid columns. Please update this table manually.', $this->getParam('db_table')), E_USER_ERROR);
+            }
+        }
+        $_db_tested = true;
+    }
+
+    /**
+     * Set the params of this object.
+     *
+     * @param  array $params   Array of param keys and values to set.
+     */
+    function setParam($params=null)
+    {
+        if (isset($params) && is_array($params)) {
+            // Merge new parameters with old overriding only those passed.
+            $this->_params = array_merge($this->_params, $params);
+        }
+    }
+
+    /**
+     * Return the value of a parameter, if it exists.
+     *
+     * @access public
+     * @param string $param        Which parameter to return.
+     * @return mixed               Configured parameter value.
+     */
+    function getParam($param)
+    {
+		$app =& App::getInstance();
+    
+        if (isset($this->_params[$param])) {
+            return $this->_params[$param];
+        } else {
+            $app->logMsg(sprintf('Parameter is not set: %s', $param), LOG_NOTICE, __FILE__, __LINE__);
+            return null;
+        }
+    }
+
+    /**
+     * Saves a version of the current record into the version table.
+     *
+     * @param string $record_table  The table containing the record.
+     * @param string $record_key    The key column for the record.
+     * @param string $record_val    The value of the key column for the record.
+     * @param string $title         The title of this record. Only used for human presentation.
+     *
+     * @return int                  The id for the version (mysql last insert id).
+     */
+    function create($record_table, $record_key, $record_val, $title='', $notes='')
+    {
+		$app =& App::getInstance();
+		$db =& DB::getInstance();
+
+        $this->initDB();
+
+        // Get current record.
+        if (!$record = $this->getCurrent($record_table, $record_key, $record_val)) {
+            $app->logMsg(sprintf('Could not create %s version, record not found: %s, %s, %s.', $title, $record_table, $record_key, $record_val), LOG_ERR, __FILE__, __LINE__);
+            return false;
+        }
+
+        // Clean-up old versions.
+        $this->deleteOld($record_table, $record_key, $record_val);
+
+        // Save as new version.
+        $db->query("
+            INSERT INTO " . $this->getParam('db_table') . " (
+                record_table,
+                record_key,
+                record_val,
+                version_data,
+                version_title,
+                version_notes,
+                saved_by_admin_id,
+                version_datetime
+            ) VALUES (
+                '" . $db->escapeString($record_table) . "',
+                '" . $db->escapeString($record_key) . "',
+                '" . $db->escapeString($record_val) . "',
+                '" . $db->escapeString(gzcompress(serialize($record), 9)) . "',
+                '" . $db->escapeString($title) . "',
+                '" . $db->escapeString($notes) . "',
+                '" . $db->escapeString($this->_auth->getVal('user_id')) . "',
+                NOW()
+            )
+        ");
+
+        return mysql_insert_id($db->getDBH());
+    }
+
+    /**
+     * Copy a version back into it's original table.
+     *
+     * @param string $version_id    The id of the version to restore.
+     *
+     * @return int                  The id for the version (mysql last insert id).
+     */
+    function restore($version_id)
+    {
+		$app =& App::getInstance();
+		$db =& DB::getInstance();
+
+        $this->initDB();
+
+        // Get version data.
+        $qid = $db->query("
+            SELECT * FROM " . $this->getParam('db_table') . "
+            WHERE version_id = '" . $db->escapeString($version_id) . "'
+        ");
+        if (!$record = mysql_fetch_assoc($qid)) {
+            $app->raiseMsg(sprintf(_("Version ID %s%s not found."), $version_id, (empty($record['version_title']) ? '' : ' (' . $record['version_title'] . ')')), MSG_WARNING, __FILE__, __LINE__);
+            $app->logMsg(sprintf(_("Version ID %s%s not found."), $version_id, (empty($record['version_title']) ? '' : ' (' . $record['version_title'] . ')')), LOG_WARNING, __FILE__, __LINE__);
+            return false;
+        }
+        $data = unserialize(gzuncompress($record['version_data']));
+
+        // Ensure saved db columns match current table schema.
+        if (!$db->columnExists($record['record_table'], array_keys($data), $this->getParam('db_schema_strict'))) {
+            $app->raiseMsg(sprintf(_("Version ID %s%s is not compatible with the current database table."), $version_id, (empty($record['version_title']) ? '' : ' (' . $record['version_title'] . ')')), MSG_ERR, __FILE__, __LINE__);
+            $app->logMsg(sprintf(_("Version ID %s%s restoration failed, DB schema does not match for table %s."), $version_id, (empty($record['version_title']) ? '' : ' (' . $record['version_title'] . ')'), $record['record_table']), LOG_ALERT, __FILE__, __LINE__);
+            return false;
+        }
+
+        // SQLize the keys of the specified versioned record.
+        $replace_keys = join(",\n", array_map(array($db, 'escapeString'), array_keys($data)));
+
+        // SQLize the keys of the values of the specified versioned record. (These are more complex because we need to account for SQL null values.)
+        $replace_values = '';
+        $comma = '';
+        foreach ($data as $v) {
+            $replace_values .= is_null($v) ? "$comma\nNULL" : "$comma\n'" . $db->escapeString($v) . "'";
+            $comma = ',';
+        }
+
+        // Replace current record with specified versioned record.
+        $db->query("
+            REPLACE INTO " . $record['record_table'] . " (
+                $replace_keys
+            ) VALUES (
+                $replace_values
+            )
+        ");
+
+        return $record;
+    }
+
+    /**
+     * Version garbage collection. Deletes versions older than min_days
+     * when quantity of versions exceeds min_qty. If quantity
+     * exceeds 100 within min_days, the oldest are deleted to bring the
+     * quantity back down to min_qty.
+     *
+     * @param string $record_table  The table containing the record.
+     * @param string $record_key    The key column for the record.
+     * @param string $record_val    The value of the key column for the record.
+     *
+     * @return mixed                Array of versions, or false if none.
+     */
+    function deleteOld($record_table, $record_key, $record_val)
+    {
+		$db =& DB::getInstance();
+	
+        $this->initDB();
+
+        // Get total number of versions for this record.
+        $qid = $db->query("
+            SELECT COUNT(*) FROM " . $this->getParam('db_table') . "
+            WHERE record_table = '" . $db->escapeString($record_table) . "'
+            AND record_key = '" . $db->escapeString($record_key) . "'
+            AND record_val = '" . $db->escapeString($record_val) . "'
+        ");
+        list($v_count) = mysql_fetch_row($qid);
+
+        if ($v_count > $this->getParam('min_qty')) {
+            if ($v_count > $this->getParam('max_qty')) {
+                // To prevent a record bomb, limit max number of versions to max_qty.
+                // First query for oldest records, selecting enough to bring total number down to min_qty.
+                $qid = $db->query("
+                    SELECT version_id FROM " . $this->getParam('db_table') . "
+                    WHERE record_table = '" . $db->escapeString($record_table) . "'
+                    AND record_key = '" . $db->escapeString($record_key) . "'
+                    AND record_val = '" . $db->escapeString($record_val) . "'
+                    ORDER BY version_datetime ASC
+                    LIMIT " . ($v_count - $this->getParam('min_qty')) . "
+                ");
+                while (list($old_id) = mysql_fetch_row($qid)) {
+                    $old_versions[] = $old_id;
+                }
+                $db->query("
+                    DELETE FROM " . $this->getParam('db_table') . "
+                    WHERE version_id IN ('" . join("','", $old_versions) . "')
+                ");
+            } else {
+                // Delete versions older than min_days, while still keeping min_qty.
+                $qid = $db->query("
+                    SELECT version_id FROM " . $this->getParam('db_table') . "
+                    WHERE record_table = '" . $db->escapeString($record_table) . "'
+                    AND record_key = '" . $db->escapeString($record_key) . "'
+                    AND record_val = '" . $db->escapeString($record_val) . "'
+                    AND DATE_ADD(version_datetime, INTERVAL '" . $this->getParam('min_days') . "' DAY) < NOW()
+                    ORDER BY version_datetime ASC
+                    LIMIT " . ($v_count - $this->getParam('min_qty')) . "
+                ");
+                while (list($old_id) = mysql_fetch_row($qid)) {
+                    $old_versions[] = $old_id;
+                }
+                if (sizeof($old_versions) > 0) {
+                    $db->query("
+                        DELETE FROM " . $this->getParam('db_table') . "
+                        WHERE version_id IN ('" . join("','", $old_versions) . "')
+                    ");
+                }
+            }
+        }
+    }
+
+    /**
+     * Get a list of versions of specified record.
+     *
+     * @param string $record_table  The table containing the record.
+     * @param string $record_key    The key column for the record.
+     * @param string $record_val    The value of the key column for the record.
+     *
+     * @return mixed                Array of versions, or false if none.
+     */
+    function getList($record_table, $record_key, $record_val)
+    {
+		$db =& DB::getInstance();
+	
+        $this->initDB();
+
+        // Get versions of this record.
+        $qid = $db->query("
+            SELECT version_id, saved_by_admin_id, version_datetime, version_title
+            FROM " . $this->getParam('db_table') . "
+            WHERE record_table = '" . $db->escapeString($record_table) . "'
+            AND record_key = '" . $db->escapeString($record_key) . "'
+            AND record_val = '" . $db->escapeString($record_val) . "'
+            ORDER BY version_datetime DESC
+        ");
+        $versions = array();
+        while ($row = mysql_fetch_assoc($qid)) {
+            // Get admin usernames.
+            $row['editor'] = $this->_auth->getVal('auth_type') . ' ' . $this->_auth->getUsername($row['saved_by_admin_id']);
+            $versions[] = $row;
+        }
+        return $versions;
+    }
+
+    /**
+     * Get the version record for a specified version id.
+     *
+     * @param string $version_id    The id of the version to restore.
+     *
+     * @return mixed                Array of data saved in version, or false if none.
+     */
+    function getVerson($version_id)
+    {
+		$db =& DB::getInstance();
+	
+        $this->initDB();
+
+        // Get version data.
+        $qid = $db->query("
+            SELECT * FROM " . $this->getParam('db_table') . "
+            WHERE version_id = '" . $db->escapeString($version_id) . "'
+        ");
+        return mysql_fetch_assoc($qid);
+    }
+
+    /**
+     * Get the data stored for a specified version id.
+     *
+     * @param string $version_id    The id of the version to restore.
+     *
+     * @return mixed                Array of data saved in version, or false if none.
+     */
+    function getData($version_id)
+    {
+		$db =& DB::getInstance();
+	
+        $this->initDB();
+
+        // Get version data.
+        $qid = $db->query("
+            SELECT * FROM " . $this->getParam('db_table') . "
+            WHERE version_id = '" . $db->escapeString($version_id) . "'
+        ");
+        $record = mysql_fetch_assoc($qid);
+        if (isset($record['version_data'])) {
+            return unserialize(gzuncompress($record['version_data']));
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * Get the current record data from the original table.
+     *
+     * @param string $version_id    The id of the version to restore.
+     *
+     * @return mixed                Array of data saved in version, or false if none.
+     */
+    function getCurrent($record_table, $record_key, $record_val)
+    {
+		$db =& DB::getInstance();
+	
+        $this->initDB();
+
+        $qid = $db->query("
+            SELECT * FROM " . $db->escapeString($record_table) . "
+            WHERE " . $db->escapeString($record_key) . " = '" . $db->escapeString($record_val) . "'
+        ");
+        if ($record = mysql_fetch_assoc($qid)) {
+            return $record;
+        } else {
+            return false;
+        }
+    }
+
+
+} // End of class.
+?>
Index: trunk/services/admins.php
===================================================================
--- trunk/services/admins.php	(revision 136)
+++ trunk/services/admins.php	(revision 137)
@@ -16,6 +16,6 @@
 require_once 'codebase/lib/TemplateGlue.inc.php';
 require_once 'codebase/lib/Prefs.inc.php';
-require_once 'codebase/lib/RecordLock.inc.php';
-require_once 'codebase/lib/RecordVersion.inc.php';
+require_once 'codebase/lib/Lock.inc.php';
+require_once 'codebase/lib/Version.inc.php';
 
 
@@ -398,5 +398,5 @@
 
     // Create version.
-    $version = RecordVersion::getInstance($GLOBALS['auth']);
+    $version = Version::getInstance($GLOBALS['auth']);
     $version->create('admin_tbl', 'admin_id', $last_insert_id, $frm['username']);
 
@@ -441,5 +441,5 @@
 
     // Create version.
-    $version = RecordVersion::getInstance($GLOBALS['auth']);
+    $version = Version::getInstance($GLOBALS['auth']);
     $version->create('admin_tbl', 'admin_id', $frm['admin_id'], $frm['username']);
 
Index: trunk/services/lock.php
===================================================================
--- trunk/services/lock.php	(revision 136)
+++ trunk/services/lock.php	(revision 137)
@@ -6,5 +6,5 @@
 
 // require_once dirname(__FILE__) . '/_config.inc.php';
-require_once 'codebase/lib/RecordLock.inc.php';
+require_once 'codebase/lib/Lock.inc.php';
 
 $auth->requireLogin();
@@ -20,6 +20,6 @@
 }
 
-if (!isset($lock) || !is_a($lock, 'RecordLock')) {
-    $lock =& RecordLock::getInstance($auth);
+if (!isset($lock) || !is_a($lock, 'Lock')) {
+    $lock =& Lock::getInstance($auth);
 }
 $lock->select(getFormData('lock_id'));
Index: trunk/services/logout.php
===================================================================
--- trunk/services/logout.php	(revision 136)
+++ trunk/services/logout.php	(revision 137)
@@ -7,6 +7,6 @@
 if (isset($auth) && method_exists($auth, 'getVal')) {
     // Delete the current user's record locks.
-    require_once 'codebase/lib/RecordLock.inc.php';
-    $lock =& RecordLock::getInstance($auth);
+    require_once 'codebase/lib/Lock.inc.php';
+    $lock =& Lock::getInstance($auth);
     $lock->removeAll($auth->getVal('user_id'));
 }
Index: trunk/services/templates/lock.ihtml
===================================================================
--- trunk/services/templates/lock.ihtml	(revision 136)
+++ trunk/services/templates/lock.ihtml	(revision 137)
@@ -1,4 +1,4 @@
 <?php
-if (!is_a($lock, 'RecordLock')) {
+if (!is_a($lock, 'Lock')) {
     return null;
 }
Index: trunk/services/versions.php
===================================================================
--- trunk/services/versions.php	(revision 136)
+++ trunk/services/versions.php	(revision 137)
@@ -10,6 +10,6 @@
 $app->sslOn();
 
-require_once 'codebase/lib/RecordVersion.inc.php';
-require_once 'codebase/lib/RecordLock.inc.php';
+require_once 'codebase/lib/Version.inc.php';
+require_once 'codebase/lib/Lock.inc.php';
 
 /******************************************************************************
@@ -17,5 +17,5 @@
  *****************************************************************************/
 
-$version = RecordVersion::getInstance($GLOBALS['auth']);
+$version = Version::getInstance($GLOBALS['auth']);
 
 // Query arguments to retain their values between page requests.
@@ -75,6 +75,6 @@
 
 case 'restore' :
-    if (!isset($lock) || !is_a($lock, 'RecordLock')) {
-        $lock =& RecordLock::getInstance($auth);
+    if (!isset($lock) || !is_a($lock, 'Lock')) {
+        $lock =& Lock::getInstance($auth);
     }
     $lock->select($record_table, $record_key, $record_val);
Index: trunk/tests/CacheTest.php
===================================================================
--- trunk/tests/CacheTest.php	(revision 137)
+++ trunk/tests/CacheTest.php	(revision 137)
@@ -0,0 +1,90 @@
+<?php
+/// FIXME: Tests not implemented.
+return;
+
+/**
+ * PHPUnit test case for Cache
+ *
+ * The method skeletons below need to be filled in with
+ * real data so that the tests will run correctly. Replace
+ * all EXPECTED_VAL and PARAM strings with real data.
+ *
+ * Created with PHPUnit_Skeleton on 2005-08-09
+ */
+require_once 'PHPUnit.php';
+class CacheTest extends PHPUnit_TestCase {
+
+    var $Cache;
+
+    function CacheTest($name)
+    {
+        $this->PHPUnit_TestCase($name);
+    }
+
+    function setUp()
+    {
+        require dirname(__FILE__) . '/_config.inc.php';
+        require_once '../lib/Cache.inc.php';
+        $this->Cache =& new Cache(PARAM);
+    }
+
+    function tearDown()
+    {
+        unset($this->Cache);
+    }
+
+    function test_getinstance()
+    {
+        $result = $this->Cache->getinstance(PARAM);
+        $expected = EXPECTED_VAL;
+        $this->assertEquals($expected, $result);
+    }
+
+    function test_setparam()
+    {
+        $result = $this->Cache->setparam(PARAM);
+        $expected = EXPECTED_VAL;
+        $this->assertEquals($expected, $result);
+    }
+
+    function test_getparam()
+    {
+        $result = $this->Cache->getparam(PARAM);
+        $expected = EXPECTED_VAL;
+        $this->assertEquals($expected, $result);
+    }
+
+    function test_putcache()
+    {
+        $result = $this->Cache->putcache(PARAM);
+        $expected = EXPECTED_VAL;
+        $this->assertEquals($expected, $result);
+    }
+
+    function test_getcache()
+    {
+        $result = $this->Cache->getcache(PARAM);
+        $expected = EXPECTED_VAL;
+        $this->assertEquals($expected, $result);
+    }
+
+    function test_iscached()
+    {
+        $result = $this->Cache->iscached(PARAM);
+        $expected = EXPECTED_VAL;
+        $this->assertEquals($expected, $result);
+    }
+
+    function test_breakcache()
+    {
+        $result = $this->Cache->breakcache(PARAM);
+        $expected = EXPECTED_VAL;
+        $this->assertEquals($expected, $result);
+    }
+
+}
+// Running the test.
+$suite = new PHPUnit_TestSuite('CacheTest');
+$result = PHPUnit::run($suite);
+echo $result->toString();
+?>
Index: trunk/tests/LockTest.php
===================================================================
--- trunk/tests/LockTest.php	(revision 137)
+++ trunk/tests/LockTest.php	(revision 137)
@@ -0,0 +1,199 @@
+<?php
+/**
+ * PHPUnit test case for Lock
+ *
+ * The method skeletons below need to be filled in with
+ * real data so that the tests will run correctly. Replace
+ * all EXPECTED_VAL and PARAM strings with real data.
+ *
+ * Created with PHPUnit_Skeleton on 2005-08-09
+ */
+require_once 'PHPUnit.php';
+class LockTest extends PHPUnit_TestCase {
+
+    var $Lock;
+    var $Auth_SQL;
+
+    function LockTest($name)
+    {
+        $this->PHPUnit_TestCase($name);
+    }
+
+    function setUp()
+    {	
+        require dirname(__FILE__) . '/_config.inc.php';
+        require_once '../lib/Lock.inc.php';
+        require_once '../lib/Auth_SQL.inc.php';
+
+        $this->Auth_SQL =& new Auth_SQL('test');
+        $this->Auth_SQL->setParam(array(
+            'db_table'          => 'test_user_tbl',
+            'db_primary_key'    => 'user_id',
+            'db_login_table'    => 'test_login_tbl',
+            'login_url'         => '/login.php',
+            'blocking'          => true
+        ));
+
+        // Use fresh user table.
+        $this->Auth_SQL->initDB(true);
+
+        // Insert test data.
+        $db =& DB::getInstance();
+        $db->query("
+            INSERT INTO test_user_tbl (
+                username,
+                userpass,
+                first_name,
+                last_name,
+                email,
+                user_type
+            ) VALUES (
+                'testuser',
+                '" . $this->Auth_SQL->encryptPassword('testpass') . "',
+                'John',
+                'Doe',
+                'john@example.com',
+                'admin'
+            )
+        ");
+        $this->Auth_SQL->login('testuser', 'testpass');
+
+        if (!$this->Auth_SQL->isLoggedIn()) {
+            trigger_error("User login failed...tests canceled.", E_USER_ERROR);
+        }
+
+        $this->Lock =& Lock::getInstance($this->Auth_SQL);
+        $this->Lock->setParam(array('db_table' => 'test_lock_tbl'));
+
+        // Use fresh lock table.
+        $this->Lock->initDB(true);
+    }
+
+    function tearDown()
+    {
+		$db =& DB::getInstance();
+	
+        unset($this->Lock);
+        unset($this->Auth_SQL);
+        $db->query("DROP TABLE IF EXISTS test_user_tbl");
+        $db->query("DROP TABLE IF EXISTS test_login_tbl");
+        $db->query("DROP TABLE IF EXISTS test_lock_tbl");
+    }
+
+    function test_getinstance()
+    {
+        $result = Lock::getinstance($this->Auth_SQL);
+        $this->assertTrue($result && is_a($result, 'Lock'));
+    }
+
+    function test_setparam()
+    {
+        $this->Lock->setparam(array('var'=>'val'));
+    }
+
+    function test_getparam()
+    {
+        $this->Lock->getparam('var');
+    }
+
+    function test_select()
+    {
+        $this->Lock->set('test_user_tbl', 'user_id', '1');
+        $result = $this->Lock->select('test_user_tbl', 'user_id', '1');
+        $this->assertTrue($result);
+    }
+
+    function test_islocked()
+    {
+        $this->Lock->select('test_user_tbl', 'user_id', '1');
+
+        $this->Lock->set('test_user_tbl', 'user_id', '1');
+        $result = $this->Lock->islocked();
+        $this->assertTrue($result, 'Lock was not set.');
+
+        $this->Lock->remove();
+        $this->Lock->select('test_user_tbl', 'user_id', '1');
+        $result = $this->Lock->islocked();
+        $this->assertFalse($result, 'Lock was not removed.');
+    }
+
+    function test_ismine()
+    {
+        $this->Lock->set('test_user_tbl', 'user_id', '1');
+        $this->Lock->select('test_user_tbl', 'user_id', '1');
+        $result = $this->Lock->ismine();
+        $this->assertTrue($result);
+    }
+
+    function test_set()
+    {
+        $this->Lock->select('test_user_tbl', 'user_id', '1');
+        $this->Lock->remove();
+        $this->Lock->set('test_user_tbl', 'user_id', '1');
+        $this->Lock->select('test_user_tbl', 'user_id', '1');
+        $result = $this->Lock->islocked();
+        $this->assertTrue($result);
+    }
+
+    function test_remove()
+    {
+        $this->Lock->select('test_user_tbl', 'user_id', '1');
+        $this->Lock->set('test_user_tbl', 'user_id', '1');
+        $this->Lock->remove();
+        $this->Lock->select('test_user_tbl', 'user_id', '1');
+        $result = $this->Lock->islocked();
+        $this->assertFalse($result);
+    }
+
+    function test_removeall()
+    {
+        $this->Lock->select('test_user_tbl', 'user_id', '1');
+        $this->Lock->set('test_user_tbl', 'user_id', '1');
+        $this->Lock->removeall();
+        $this->Lock->select('test_user_tbl', 'user_id', '1');
+        $result = $this->Lock->islocked();
+        $this->assertFalse($result);
+    }
+
+    function test__auto_timeout()
+    {
+        $this->Lock->_auto_timeout();
+    }
+
+    function test_getid()
+    {
+        $this->Lock->select('test_user_tbl', 'user_id', '1');
+        $this->Lock->set('test_user_tbl', 'user_id', '1');
+        $result = $this->Lock->getid();
+        $this->assertTrue('' != $result);
+        $this->assertTrue(is_numeric($result));
+    }
+
+    function test_gettitle()
+    {
+        $this->Lock->select('test_user_tbl', 'user_id', '1');
+        $this->Lock->set('test_user_tbl', 'user_id', '1', 'userlock');
+        $result = $this->Lock->gettitle();
+        $this->assertEquals('userlock', $result);
+    }
+
+    function test_geteditor()
+    {
+        $this->Lock->select('test_user_tbl', 'user_id', '1');
+        $this->Lock->set('test_user_tbl', 'user_id', '1', 'userlock');
+        $result = $this->Lock->geteditor();
+        $this->assertEquals('testuser', $result);
+    }
+
+    function test_getsecondselapsed()
+    {
+        $result = $this->Lock->getsecondselapsed();
+        $this->assertType('integer', $result);
+    }
+
+}
+// Running the test.
+$suite = new PHPUnit_TestSuite('LockTest');
+$result = PHPUnit::run($suite);
+echo $result->toString();
+?>
Index: trunk/tests/RecordLockTest.php
===================================================================
--- trunk/tests/RecordLockTest.php	(revision 136)
+++ 	(revision )
@@ -1,199 +1,0 @@
-<?php
-/**
- * PHPUnit test case for RecordLock
- *
- * The method skeletons below need to be filled in with
- * real data so that the tests will run correctly. Replace
- * all EXPECTED_VAL and PARAM strings with real data.
- *
- * Created with PHPUnit_Skeleton on 2005-08-09
- */
-require_once 'PHPUnit.php';
-class RecordLockTest extends PHPUnit_TestCase {
-
-    var $RecordLock;
-    var $Auth_SQL;
-
-    function RecordLockTest($name)
-    {
-        $this->PHPUnit_TestCase($name);
-    }
-
-    function setUp()
-    {	
-        require dirname(__FILE__) . '/_config.inc.php';
-        require_once '../lib/RecordLock.inc.php';
-        require_once '../lib/Auth_SQL.inc.php';
-
-        $this->Auth_SQL =& new Auth_SQL('test');
-        $this->Auth_SQL->setParam(array(
-            'db_table'          => 'test_user_tbl',
-            'db_primary_key'    => 'user_id',
-            'db_login_table'    => 'test_login_tbl',
-            'login_url'         => '/login.php',
-            'blocking'          => true
-        ));
-
-        // Use fresh user table.
-        $this->Auth_SQL->initDB(true);
-
-        // Insert test data.
-        $db =& DB::getInstance();
-        $db->query("
-            INSERT INTO test_user_tbl (
-                username,
-                userpass,
-                first_name,
-                last_name,
-                email,
-                user_type
-            ) VALUES (
-                'testuser',
-                '" . $this->Auth_SQL->encryptPassword('testpass') . "',
-                'John',
-                'Doe',
-                'john@example.com',
-                'admin'
-            )
-        ");
-        $this->Auth_SQL->login('testuser', 'testpass');
-
-        if (!$this->Auth_SQL->isLoggedIn()) {
-            trigger_error("User login failed...tests canceled.", E_USER_ERROR);
-        }
-
-        $this->RecordLock =& RecordLock::getInstance($this->Auth_SQL);
-        $this->RecordLock->setParam(array('db_table' => 'test_lock_tbl'));
-
-        // Use fresh lock table.
-        $this->RecordLock->initDB(true);
-    }
-
-    function tearDown()
-    {
-		$db =& DB::getInstance();
-	
-        unset($this->RecordLock);
-        unset($this->Auth_SQL);
-        $db->query("DROP TABLE IF EXISTS test_user_tbl");
-        $db->query("DROP TABLE IF EXISTS test_login_tbl");
-        $db->query("DROP TABLE IF EXISTS test_lock_tbl");
-    }
-
-    function test_getinstance()
-    {
-        $result = RecordLock::getinstance($this->Auth_SQL);
-        $this->assertTrue($result && is_a($result, 'RecordLock'));
-    }
-
-    function test_setparam()
-    {
-        $this->RecordLock->setparam(array('var'=>'val'));
-    }
-
-    function test_getparam()
-    {
-        $this->RecordLock->getparam('var');
-    }
-
-    function test_select()
-    {
-        $this->RecordLock->set('test_user_tbl', 'user_id', '1');
-        $result = $this->RecordLock->select('test_user_tbl', 'user_id', '1');
-        $this->assertTrue($result);
-    }
-
-    function test_islocked()
-    {
-        $this->RecordLock->select('test_user_tbl', 'user_id', '1');
-
-        $this->RecordLock->set('test_user_tbl', 'user_id', '1');
-        $result = $this->RecordLock->islocked();
-        $this->assertTrue($result, 'Lock was not set.');
-
-        $this->RecordLock->remove();
-        $this->RecordLock->select('test_user_tbl', 'user_id', '1');
-        $result = $this->RecordLock->islocked();
-        $this->assertFalse($result, 'Lock was not removed.');
-    }
-
-    function test_ismine()
-    {
-        $this->RecordLock->set('test_user_tbl', 'user_id', '1');
-        $this->RecordLock->select('test_user_tbl', 'user_id', '1');
-        $result = $this->RecordLock->ismine();
-        $this->assertTrue($result);
-    }
-
-    function test_set()
-    {
-        $this->RecordLock->select('test_user_tbl', 'user_id', '1');
-        $this->RecordLock->remove();
-        $this->RecordLock->set('test_user_tbl', 'user_id', '1');
-        $this->RecordLock->select('test_user_tbl', 'user_id', '1');
-        $result = $this->RecordLock->islocked();
-        $this->assertTrue($result);
-    }
-
-    function test_remove()
-    {
-        $this->RecordLock->select('test_user_tbl', 'user_id', '1');
-        $this->RecordLock->set('test_user_tbl', 'user_id', '1');
-        $this->RecordLock->remove();
-        $this->RecordLock->select('test_user_tbl', 'user_id', '1');
-        $result = $this->RecordLock->islocked();
-        $this->assertFalse($result);
-    }
-
-    function test_removeall()
-    {
-        $this->RecordLock->select('test_user_tbl', 'user_id', '1');
-        $this->RecordLock->set('test_user_tbl', 'user_id', '1');
-        $this->RecordLock->removeall();
-        $this->RecordLock->select('test_user_tbl', 'user_id', '1');
-        $result = $this->RecordLock->islocked();
-        $this->assertFalse($result);
-    }
-
-    function test__auto_timeout()
-    {
-        $this->RecordLock->_auto_timeout();
-    }
-
-    function test_getid()
-    {
-        $this->RecordLock->select('test_user_tbl', 'user_id', '1');
-        $this->RecordLock->set('test_user_tbl', 'user_id', '1');
-        $result = $this->RecordLock->getid();
-        $this->assertTrue('' != $result);
-        $this->assertTrue(is_numeric($result));
-    }
-
-    function test_gettitle()
-    {
-        $this->RecordLock->select('test_user_tbl', 'user_id', '1');
-        $this->RecordLock->set('test_user_tbl', 'user_id', '1', 'userlock');
-        $result = $this->RecordLock->gettitle();
-        $this->assertEquals('userlock', $result);
-    }
-
-    function test_geteditor()
-    {
-        $this->RecordLock->select('test_user_tbl', 'user_id', '1');
-        $this->RecordLock->set('test_user_tbl', 'user_id', '1', 'userlock');
-        $result = $this->RecordLock->geteditor();
-        $this->assertEquals('testuser', $result);
-    }
-
-    function test_getsecondselapsed()
-    {
-        $result = $this->RecordLock->getsecondselapsed();
-        $this->assertType('integer', $result);
-    }
-
-}
-// Running the test.
-$suite = new PHPUnit_TestSuite('RecordLockTest');
-$result = PHPUnit::run($suite);
-echo $result->toString();
-?>
Index: trunk/tests/RecordVersionTest.php
===================================================================
--- trunk/tests/RecordVersionTest.php	(revision 136)
+++ 	(revision )
@@ -1,177 +1,0 @@
-<?php
-/**
- * PHPUnit test case for RecordVersion
- *
- * The method skeletons below need to be filled in with
- * real data so that the tests will run correctly. Replace
- * all EXPECTED_VAL and PARAM strings with real data.
- *
- * Created with PHPUnit_Skeleton on 2005-08-09
- */
-require_once 'PHPUnit.php';
-class RecordVersionTest extends PHPUnit_TestCase {
-
-    var $RecordVersion;
-    var $Auth_SQL;
-
-    function RecordVersionTest($name)
-    {
-        $this->PHPUnit_TestCase($name);
-    }
-
-    function setUp()
-    {	
-        require dirname(__FILE__) . '/_config.inc.php';
-        require_once '../lib/RecordVersion.inc.php';
-
-        require_once '../lib/Auth_SQL.inc.php';
-        $this->Auth_SQL =& new Auth_SQL('testauth');
-        $this->Auth_SQL->setParam(array(
-            'db_table'          => 'test_user_tbl',
-            'db_primary_key'    => 'user_id',
-            'db_login_table'    => 'test_login_tbl',
-            'login_url'         => '/login.php',
-            'blocking'          => true
-        ));
-
-        // Use fresh user table.
-        $this->Auth_SQL->initDB(true);
-
-        // Insert test data.
-        $db =& DB::getInstance();
-        $db->query("
-            INSERT INTO test_user_tbl (
-                username,
-                userpass,
-                first_name,
-                last_name,
-                email,
-                user_type
-            ) VALUES (
-                'testuser',
-                md5('testpass'),
-                'John',
-                'Doe',
-                'john@example.com',
-                'admin'
-            )
-        ");
-
-        $this->Auth_SQL->login('testuser', 'testpass');
-
-        $this->RecordVersion =& RecordVersion::getInstance($this->Auth_SQL);
-        $this->RecordVersion->setParam(array('db_table' => 'test_version_tbl'));
-
-        // Use fresh version table.
-        $this->RecordVersion->initDB(true);
-    }
-
-    function tearDown()
-    {
-		$db =& DB::getInstance();
-	
-        unset($this->RecordVersion);
-        unset($this->Auth_SQL);
-        $db->query("DROP TABLE IF EXISTS test_user_tbl");
-        $db->query("DROP TABLE IF EXISTS test_login_tbl");
-        $db->query("DROP TABLE IF EXISTS test_version_tbl");
-    }
-
-    function test_getinstance()
-    {
-        $result = RecordVersion::getinstance($this->Auth_SQL);
-        $this->assertTrue($result && is_a($result, 'RecordVersion'));
-    }
-
-    function test_setparam()
-    {
-        $this->RecordVersion->setparam(array('var'=>'val'));
-    }
-
-    function test_getparam()
-    {
-        $this->RecordVersion->getparam('var');
-    }
-
-    function test_create()
-    {
-        $result = $this->RecordVersion->create('test_user_tbl', 'user_id', '1', 'Test User', 'First version of user');
-        $this->assertTrue($result);
-    }
-
-    function test_restore()
-    {
-        $current = $this->RecordVersion->getCurrent('test_user_tbl', 'user_id', '1');
-        $version_id = $this->RecordVersion->create('test_user_tbl', 'user_id', '1', 'Test User', 'First version of user');
-        $versioned = $this->RecordVersion->getData($version_id);
-        $result = $this->RecordVersion->restore($version_id);
-        $restored = $this->RecordVersion->getCurrent('test_user_tbl', 'user_id', '1');
-        $this->assertTrue(is_array($result), 'Restore did not return array.');
-        $this->assertTrue($current === $versioned && $versioned === $restored, 'Restored version does not match original.');
-    }
-
-    function test_deleteold()
-    {
-        // Creat 3 test versions.
-        $this->RecordVersion->create('test_user_tbl', 'user_id', '1', 'Test 1', '1 version of user');
-        $this->RecordVersion->create('test_user_tbl', 'user_id', '1', 'Test 2', '2 version of user');
-        $this->RecordVersion->create('test_user_tbl', 'user_id', '1', 'Test 3', '3 version of user');
-
-        $a = $this->RecordVersion->getList('test_user_tbl', 'user_id', '1');
-
-        $this->RecordVersion->deleteold('test_user_tbl', 'user_id', '1');
-        $b = $this->RecordVersion->getList('test_user_tbl', 'user_id', '1');
-
-        $this->RecordVersion->setparam(array('max_qty'=>2));
-        $this->RecordVersion->setparam(array('min_qty'=>1));
-        $this->RecordVersion->setparam(array('min_days'=>0));
-        $this->RecordVersion->deleteold('test_user_tbl', 'user_id', '1');
-        $c = $this->RecordVersion->getList('test_user_tbl', 'user_id', '1');
-
-        $this->RecordVersion->setparam(array('max_qty'=>0));
-        $this->RecordVersion->setparam(array('min_qty'=>0));
-        $this->RecordVersion->setparam(array('min_days'=>0));
-        $this->RecordVersion->deleteold('test_user_tbl', 'user_id', '1');
-        $d = $this->RecordVersion->getList('test_user_tbl', 'user_id', '1');
-
-        $this->assertTrue(sizeof($a) == 3, 'A is wrong');
-        $this->assertTrue(sizeof($b) == 3, 'B is wrong');
-        $this->assertTrue(sizeof($c) == 1, 'C is wrong');
-        $this->assertTrue(sizeof($d) == 0, 'D is wrong');
-    }
-
-    function test_getlist()
-    {
-        $this->RecordVersion->create('test_user_tbl', 'user_id', '1', 'Test 1', '1 version of user');
-        $this->RecordVersion->create('test_user_tbl', 'user_id', '1', 'Test 2', '2 version of user');
-        $this->RecordVersion->create('test_user_tbl', 'user_id', '1', 'Test 3', '3 version of user');
-        $result = $this->RecordVersion->getList('test_user_tbl', 'user_id', '1');
-        $this->assertTrue(is_array($result) && !empty($result));
-    }
-
-    function test_getverson()
-    {
-        $version_id = $this->RecordVersion->create('test_user_tbl', 'user_id', '1', 'Test User', 'First version of user');
-        $result = $this->RecordVersion->getverson($version_id);
-        $this->assertTrue(is_array($result) && !empty($result));
-    }
-
-    function test_getdata()
-    {
-        $version_id = $this->RecordVersion->create('test_user_tbl', 'user_id', '1', 'Test User', 'First version of user');
-        $result = $this->RecordVersion->getdata($version_id);
-        $this->assertTrue(is_array($result) && !empty($result));
-    }
-
-    function test_getcurrent()
-    {
-        $result = $this->RecordVersion->getCurrent('test_user_tbl', 'user_id', '1');
-        $this->assertTrue(is_array($result) && !empty($result));
-    }
-
-}
-// Running the test.
-$suite = new PHPUnit_TestSuite('RecordVersionTest');
-$result = PHPUnit::run($suite);
-echo $result->toString();
-?>
Index: trunk/tests/SessionCacheTest.php
===================================================================
--- trunk/tests/SessionCacheTest.php	(revision 136)
+++ 	(revision )
@@ -1,90 +1,0 @@
-<?php
-/// FIXME: Tests not implemented.
-return;
-
-/**
- * PHPUnit test case for Cache
- *
- * The method skeletons below need to be filled in with
- * real data so that the tests will run correctly. Replace
- * all EXPECTED_VAL and PARAM strings with real data.
- *
- * Created with PHPUnit_Skeleton on 2005-08-09
- */
-require_once 'PHPUnit.php';
-class CacheTest extends PHPUnit_TestCase {
-
-    var $Cache;
-
-    function CacheTest($name)
-    {
-        $this->PHPUnit_TestCase($name);
-    }
-
-    function setUp()
-    {
-        require dirname(__FILE__) . '/_config.inc.php';
-        require_once '../lib/Cache.inc.php';
-        $this->Cache =& new Cache(PARAM);
-    }
-
-    function tearDown()
-    {
-        unset($this->Cache);
-    }
-
-    function test_getinstance()
-    {
-        $result = $this->Cache->getinstance(PARAM);
-        $expected = EXPECTED_VAL;
-        $this->assertEquals($expected, $result);
-    }
-
-    function test_setparam()
-    {
-        $result = $this->Cache->setparam(PARAM);
-        $expected = EXPECTED_VAL;
-        $this->assertEquals($expected, $result);
-    }
-
-    function test_getparam()
-    {
-        $result = $this->Cache->getparam(PARAM);
-        $expected = EXPECTED_VAL;
-        $this->assertEquals($expected, $result);
-    }
-
-    function test_putcache()
-    {
-        $result = $this->Cache->putcache(PARAM);
-        $expected = EXPECTED_VAL;
-        $this->assertEquals($expected, $result);
-    }
-
-    function test_getcache()
-    {
-        $result = $this->Cache->getcache(PARAM);
-        $expected = EXPECTED_VAL;
-        $this->assertEquals($expected, $result);
-    }
-
-    function test_iscached()
-    {
-        $result = $this->Cache->iscached(PARAM);
-        $expected = EXPECTED_VAL;
-        $this->assertEquals($expected, $result);
-    }
-
-    function test_breakcache()
-    {
-        $result = $this->Cache->breakcache(PARAM);
-        $expected = EXPECTED_VAL;
-        $this->assertEquals($expected, $result);
-    }
-
-}
-// Running the test.
-$suite = new PHPUnit_TestSuite('CacheTest');
-$result = PHPUnit::run($suite);
-echo $result->toString();
-?>
Index: trunk/tests/VersionTest.php
===================================================================
--- trunk/tests/VersionTest.php	(revision 137)
+++ trunk/tests/VersionTest.php	(revision 137)
@@ -0,0 +1,177 @@
+<?php
+/**
+ * PHPUnit test case for Version
+ *
+ * The method skeletons below need to be filled in with
+ * real data so that the tests will run correctly. Replace
+ * all EXPECTED_VAL and PARAM strings with real data.
+ *
+ * Created with PHPUnit_Skeleton on 2005-08-09
+ */
+require_once 'PHPUnit.php';
+class VersionTest extends PHPUnit_TestCase {
+
+    var $Version;
+    var $Auth_SQL;
+
+    function VersionTest($name)
+    {
+        $this->PHPUnit_TestCase($name);
+    }
+
+    function setUp()
+    {	
+        require dirname(__FILE__) . '/_config.inc.php';
+        require_once '../lib/Version.inc.php';
+
+        require_once '../lib/Auth_SQL.inc.php';
+        $this->Auth_SQL =& new Auth_SQL('testauth');
+        $this->Auth_SQL->setParam(array(
+            'db_table'          => 'test_user_tbl',
+            'db_primary_key'    => 'user_id',
+            'db_login_table'    => 'test_login_tbl',
+            'login_url'         => '/login.php',
+            'blocking'          => true
+        ));
+
+        // Use fresh user table.
+        $this->Auth_SQL->initDB(true);
+
+        // Insert test data.
+        $db =& DB::getInstance();
+        $db->query("
+            INSERT INTO test_user_tbl (
+                username,
+                userpass,
+                first_name,
+                last_name,
+                email,
+                user_type
+            ) VALUES (
+                'testuser',
+                md5('testpass'),
+                'John',
+                'Doe',
+                'john@example.com',
+                'admin'
+            )
+        ");
+
+        $this->Auth_SQL->login('testuser', 'testpass');
+
+        $this->Version =& Version::getInstance($this->Auth_SQL);
+        $this->Version->setParam(array('db_table' => 'test_version_tbl'));
+
+        // Use fresh version table.
+        $this->Version->initDB(true);
+    }
+
+    function tearDown()
+    {
+		$db =& DB::getInstance();
+	
+        unset($this->Version);
+        unset($this->Auth_SQL);
+        $db->query("DROP TABLE IF EXISTS test_user_tbl");
+        $db->query("DROP TABLE IF EXISTS test_login_tbl");
+        $db->query("DROP TABLE IF EXISTS test_version_tbl");
+    }
+
+    function test_getinstance()
+    {
+        $result = Version::getinstance($this->Auth_SQL);
+        $this->assertTrue($result && is_a($result, 'Version'));
+    }
+
+    function test_setparam()
+    {
+        $this->Version->setparam(array('var'=>'val'));
+    }
+
+    function test_getparam()
+    {
+        $this->Version->getparam('var');
+    }
+
+    function test_create()
+    {
+        $result = $this->Version->create('test_user_tbl', 'user_id', '1', 'Test User', 'First version of user');
+        $this->assertTrue($result);
+    }
+
+    function test_restore()
+    {
+        $current = $this->Version->getCurrent('test_user_tbl', 'user_id', '1');
+        $version_id = $this->Version->create('test_user_tbl', 'user_id', '1', 'Test User', 'First version of user');
+        $versioned = $this->Version->getData($version_id);
+        $result = $this->Version->restore($version_id);
+        $restored = $this->Version->getCurrent('test_user_tbl', 'user_id', '1');
+        $this->assertTrue(is_array($result), 'Restore did not return array.');
+        $this->assertTrue($current === $versioned && $versioned === $restored, 'Restored version does not match original.');
+    }
+
+    function test_deleteold()
+    {
+        // Creat 3 test versions.
+        $this->Version->create('test_user_tbl', 'user_id', '1', 'Test 1', '1 version of user');
+        $this->Version->create('test_user_tbl', 'user_id', '1', 'Test 2', '2 version of user');
+        $this->Version->create('test_user_tbl', 'user_id', '1', 'Test 3', '3 version of user');
+
+        $a = $this->Version->getList('test_user_tbl', 'user_id', '1');
+
+        $this->Version->deleteold('test_user_tbl', 'user_id', '1');
+        $b = $this->Version->getList('test_user_tbl', 'user_id', '1');
+
+        $this->Version->setparam(array('max_qty'=>2));
+        $this->Version->setparam(array('min_qty'=>1));
+        $this->Version->setparam(array('min_days'=>0));
+        $this->Version->deleteold('test_user_tbl', 'user_id', '1');
+        $c = $this->Version->getList('test_user_tbl', 'user_id', '1');
+
+        $this->Version->setparam(array('max_qty'=>0));
+        $this->Version->setparam(array('min_qty'=>0));
+        $this->Version->setparam(array('min_days'=>0));
+        $this->Version->deleteold('test_user_tbl', 'user_id', '1');
+        $d = $this->Version->getList('test_user_tbl', 'user_id', '1');
+
+        $this->assertTrue(sizeof($a) == 3, 'A is wrong');
+        $this->assertTrue(sizeof($b) == 3, 'B is wrong');
+        $this->assertTrue(sizeof($c) == 1, 'C is wrong');
+        $this->assertTrue(sizeof($d) == 0, 'D is wrong');
+    }
+
+    function test_getlist()
+    {
+        $this->Version->create('test_user_tbl', 'user_id', '1', 'Test 1', '1 version of user');
+        $this->Version->create('test_user_tbl', 'user_id', '1', 'Test 2', '2 version of user');
+        $this->Version->create('test_user_tbl', 'user_id', '1', 'Test 3', '3 version of user');
+        $result = $this->Version->getList('test_user_tbl', 'user_id', '1');
+        $this->assertTrue(is_array($result) && !empty($result));
+    }
+
+    function test_getverson()
+    {
+        $version_id = $this->Version->create('test_user_tbl', 'user_id', '1', 'Test User', 'First version of user');
+        $result = $this->Version->getverson($version_id);
+        $this->assertTrue(is_array($result) && !empty($result));
+    }
+
+    function test_getdata()
+    {
+        $version_id = $this->Version->create('test_user_tbl', 'user_id', '1', 'Test User', 'First version of user');
+        $result = $this->Version->getdata($version_id);
+        $this->assertTrue(is_array($result) && !empty($result));
+    }
+
+    function test_getcurrent()
+    {
+        $result = $this->Version->getCurrent('test_user_tbl', 'user_id', '1');
+        $this->assertTrue(is_array($result) && !empty($result));
+    }
+
+}
+// Running the test.
+$suite = new PHPUnit_TestSuite('VersionTest');
+$result = PHPUnit::run($suite);
+echo $result->toString();
+?>
