[Cs-webapplibs-commits] SF.net SVN: cs-webapplibs:[127] trunk/0.3
Status: Beta
Brought to you by:
crazedsanity
From: <cra...@us...> - 2009-08-20 20:39:44
|
Revision: 127 http://cs-webapplibs.svn.sourceforge.net/cs-webapplibs/?rev=127&view=rev Author: crazedsanity Date: 2009-08-20 20:39:35 +0000 (Thu, 20 Aug 2009) Log Message: ----------- All webapp-related items moved here from cs-content... NOTE::: nearly all files now have the "svn:keywords" property set. NOTE2:: this is done to facilitate much faster changes to cs-content. While it may slow development of cs-webapplibs, there is also a lot of work being done to build unit tests there: this should hopefully avoid unexpected breakage in code during upgrades. This also makes upgrading of the database-reliant stuff (like cs_phpDB) to be more easily upgraded. CODE MOVED FROM cs-content::: * /cs_bbCodeParser.class.php * /cs_phpDB.class.php (including db_types & abstract) * /cs_sessionDB.class.php (including schema files) * /cs_siteConfig.class.php * /cs_tabs.class.php * /abstract/cs_phpDB.abstract.class.php * /tests/testOfCSPHPDB.php CHANGED REQUIRE_ONCE PATHS::: * /contentSystem.class.php (cs_sessionDB) MISC::: * /contentSystem.class.php: -- MAIN::: don't require cs_tabs -- initialize_locals(): drop cs_tabs stuff (unneeded) Modified Paths: -------------- trunk/0.3/cs_webdbupgrade.class.php Added Paths: ----------- trunk/0.3/abstract/cs_phpDB.abstract.class.php trunk/0.3/cs_bbCodeParser.class.php trunk/0.3/cs_phpDB.class.php trunk/0.3/cs_sessionDB.class.php trunk/0.3/cs_siteConfig.class.php trunk/0.3/cs_tabs.class.php trunk/0.3/db_types/ trunk/0.3/db_types/cs_phpDB__mysql.class.php trunk/0.3/db_types/cs_phpDB__pgsql.class.php trunk/0.3/db_types/cs_phpDB__sqlite.class.php trunk/0.3/setup/db_session_schema.mysql.sql trunk/0.3/setup/db_session_schema.pgsql.sql trunk/0.3/tests/testOfCSPHPDB.php Property Changed: ---------------- trunk/0.3/docs/CREDITS trunk/0.3/docs/LICENSE trunk/0.3/docs/README.txt trunk/0.3/docs/SETUP.txt trunk/0.3/tests/example_test.php trunk/0.3/tests/testOfCSWebAppLibs.php Added: trunk/0.3/abstract/cs_phpDB.abstract.class.php =================================================================== --- trunk/0.3/abstract/cs_phpDB.abstract.class.php (rev 0) +++ trunk/0.3/abstract/cs_phpDB.abstract.class.php 2009-08-20 20:39:35 UTC (rev 127) @@ -0,0 +1,166 @@ +<?php +/* + * Created on Jan 29, 2009 + * + * FILE INFORMATION: + * + * $HeadURL$ + * $Id$ + * $LastChangedDate$ + * $LastChangedBy$ + * $LastChangedRevision$ + */ + +abstract class cs_phpDBAbstract { + + /** Internal result set pointer. */ + protected $result = NULL; + + /** Internal error code. */ + protected $errorCode = 0; + + /** Status of the current transaction. */ + protected $transStatus = NULL; + + /** Whether there is a transaction in progress or not. */ + protected $inTrans = FALSE; + + /** Holds the last query performed. */ + protected $lastQuery = NULL; + + /** List of queries that have been run */ + protected $queryList=array(); + + /** How many seconds to wait for a query before cancelling it. */ + protected $timeOutSeconds = NULL; + + /** Internal check to determine if a connection has been established. */ + protected $isConnected=FALSE; + + /** Internal check to determine if the parameters have been set. */ + protected $paramsAreSet=FALSE; + + /** Resource handle. */ + protected $connectionID = -1; + + /** Hostname or IP to connect to */ + protected $host; + + /** Port to connect to (default for Postgres is 5432) */ + protected $port; + + /** Name of the database */ + protected $dbname; + + /** Username to connect to the database */ + protected $user; + + /** password to connect to the database */ + protected $password; + + /** Row counter for looping through records */ + protected $row = -1; + + /** cs_globalFunctions object, for string stuff. */ + protected $gfObj; + + /** Internal check to ensure the object has been properly created. */ + protected $isInitialized=FALSE; + + /** List of prepared statements, indexed off the name, with the sub-array being fieldname=>dataType. */ + protected $preparedStatements = array(); + + /** Set to TRUE to save all queries into an array. */ + protected $useQueryList=FALSE; + + /** array that essentially remembers how many times beginTrans() was called. */ + protected $transactionTree = NULL; + + + + //Define some abstract methods so they MUST be provided in order for things to work. + abstract public function set_db_info(array $params); + abstract public function close(); + abstract public function connect(array $dbParams=NULL, $forceNewConnection=FALSE); + abstract public function exec($query); + abstract public function errorMsg($setMessage=null, $logError=null); + abstract public function fobject(); + abstract public function farray(); + abstract public function farray_fieldnames($index=null, $numbered=null,$unsetIndex=1); + abstract public function farray_nvp($name, $value); + abstract public function farray_numbered(); + abstract public function numAffected(); + abstract public function numRows(); + abstract public function is_connected(); + + + //========================================================================= + public function __construct() { + $this->gfObj = new cs_globalFunctions; + $this->isInitialized = true; + }//end __construct() + //========================================================================= + + + + //========================================================================= + /** + * Make sure the object is sane. + */ + final protected function sanity_check() { + if($this->isInitialized !== TRUE) { + throw new exception(__METHOD__ .": not properly initialized"); + } + }//end sanity_check() + //========================================================================= + + + + //========================================================================= + /** + * Disconnect from the database (calls internal "close()" method). + */ + public function disconnect() { + return($this->close()); + }//end disconnect() + //========================================================================= + + + + //========================================================================= + public function affectedRows() { + return($this->numAffected()); + }//end affectedRows() + //========================================================================= + + + + //========================================================================= + public function currRow() { + return($this->row); + }//end currRow() + //========================================================================= + + + + //========================================================================= + public function querySafe($string) { + return($this->gfObj->cleanString($string,"query")); + }//end querySafe() + //========================================================================= + + + + //========================================================================= + /** + * Make it SQL safe. + */ + public function sqlSafe($string) { + return($this->gfObj->cleanString($string,"sql")); + }//end sqlSafe() + //========================================================================= + + + +} +?> \ No newline at end of file Property changes on: trunk/0.3/abstract/cs_phpDB.abstract.class.php ___________________________________________________________________ Added: svn:keywords + Id Author Revision HeadURL Date Added: trunk/0.3/cs_bbCodeParser.class.php =================================================================== --- trunk/0.3/cs_bbCodeParser.class.php (rev 0) +++ trunk/0.3/cs_bbCodeParser.class.php 2009-08-20 20:39:35 UTC (rev 127) @@ -0,0 +1,165 @@ +<?php +/** + * Created on 2007-09-26 + * + * + * SVN INFORMATION::: + * ------------------ + * SVN Signature::::::: $Id$ + * Last Author::::::::: $Author$ + * Current Revision:::: $Revision$ + * Repository Location: $HeadURL$ + * Last Updated:::::::: $Date$ + * + * + * Originally from a snippet (just the function) on PHPFreaks.com: http://www.phpfreaks.com/quickcode/BBCode/712.php + * The original code had parse errors, so it had to be fixed... While it was posted as just a basic function, + * the code within (such as the reference to "$this->bbCodeData" indicated it was from a class... so it has + * been converted. + */ + +require_once(dirname(__FILE__) ."/abstract/cs_webapplibs.abstract.class.php"); + +class cs_bbCodeParser extends cs_contentAbstract { + + /** Array containing all the codes & how to parse them. */ + private $bbCodeData = NULL; + + //========================================================================= + /** + * Setup internal structures. + */ + function __construct() { + parent::__construct(false); + # Which BBCode is accepted here + $this->bbCodeData = array( + 'bold' => array( + 'start' => array('[b]', '\[b\](.*)', '<b>\\1'), + 'end' => array('[/b]', '\[\/b\]', '</b>'), + ), + + 'underline' => array( + 'start' => array('[u]', '\[u\](.*)', '<u>\\1'), + 'end' => array('[/u]', '\[\/u\]', '</u>'), + ), + + 'italic' => array( + 'start' => array('[i]', '\[i\](.*)', '<i>\\1'), + 'end' => array('[/i]', '\[\/i\]', '</i>'), + ), + + 'image' => array( + 'start' => array('[img]', '\[img\](http:\/\/|https:\/\/|ftp:\/\/|\/)(.*)(.jpg|.jpeg|.bmp|.gif|.png)', '<img src=\'\\1\\2\\3\' />'), + 'end' => array('[/img]', '\[\/img\]', ''), + ), + + # [url]http://x.com[/url] + 'url1' => array( + 'start' => array('[url]', '\[url\](http:\/\/|https:\/\/|ftp:\/\/)(.*)', '<a target="_blank" href=\'\\1\\2\'>\\1\\2'), + 'end' => array('[/url]', '\[\/url\]', '</a>'), + ), + + # [url=http://x.com]stuff[/url] + 'url2' => array( + 'start' => array('[url]', '\[url=(http:\/\/|https:\/\/|ftp:\/\/)(.*)\](.*)', '<a target="_blank" href=\'\\1\\2\'>\\3'), + 'end' => array('[/url]', '\[\/url\]', '</a>'), + ), + + 'code' => array( + 'start' => array('[code]', '\[code\](.*)', '<br /><br /><b>CODE</b>:<div class="code">\\1'), + 'end' => array('[/code]', '\[\/code\]', '</div><br />'), + ), + ); + }//end __construct() + //========================================================================= + + + + //========================================================================= + /** + * Ensure the object is initialized properly, throw exception if not. + */ + private function isInitialized() { + if(!is_array($this->bbCodeData) || !count($this->bbCodeData)) { + throw new exception(__METHOD__ .": BBCode array not initialized"); + } + }//end isInitialized() + //========================================================================= + + + + //========================================================================= + /** + * Parse BBCode from the given string & return it with formatting. + */ + function parseString($data, $newlines2BR=FALSE) { + if(is_string($data) && strlen($data) > 10) { + $this->isInitialized(); + $data = str_replace("\n", '||newline||', $data); + + foreach( $this->bbCodeData as $k => $v ) { + if(isset($this->bbCodeData[$k]['special'])) { + $myMatches = array(); + $regex = '/'. $this->bbCodeData[$k]['start'][1] . $this->bbCodeData[$k]['end'][1] .'/'; + $x = preg_match_all($regex .'U', $data, $myMatches); + + if(count($myMatches[1])) { + $funcName = $v['special']; + $myArgs = $myMatches[1]; + $myArgs = array_unique($myArgs); + + foreach($myArgs as $index=>$value) { + $showThis = $this->$funcName($value); + $replaceThis = str_replace(array('[', ']'), array('\\[', '\\]'), $myMatches[0][$index]); + $data = preg_replace('/'. $replaceThis .'/U', $showThis, $data); + } + } + } + else { + $data = preg_replace("/".$this->bbCodeData[$k]['start'][1].$this->bbCodeData[$k]['end'][1]."/U", $this->bbCodeData[$k]['start'][2].$this->bbCodeData[$k]['end'][2], $data); + } + } + + $replaceNewlineStr = "\n"; + if($newlines2BR) { + $replaceNewlineStr = "<br />\n"; + } + $data = str_replace('||newline||', $replaceNewlineStr, $data); + + } + return $data; + }//end parseString() + //========================================================================= + + + + //========================================================================= + /** + * Enables extending classes to register a bbCode with special parsing. + * + * NOTE: right now, this will only handle syntax like "[{bbCodeString}={arg}]". + */ + protected function register_code_with_callback($bbCodeString, $method) { + + if(method_exists($this, $method)) { + $this->bbCodeData[$bbCodeString] = array( + 'special' => $method, + 'start' => array( + '['. $bbCodeString .']', + '\['. $bbCodeString .'=(.*)' + ), + 'end' => array( + '', + '\]' + ) + ); + } + else { + throw new exception(__METHOD__ .": method (". $method .") doesn't exist"); + } + + }//end register_code_with_callback() + //========================================================================= + +} +?> Property changes on: trunk/0.3/cs_bbCodeParser.class.php ___________________________________________________________________ Added: svn:keywords + Id Author Revision HeadURL Date Added: trunk/0.3/cs_phpDB.class.php =================================================================== --- trunk/0.3/cs_phpDB.class.php (rev 0) +++ trunk/0.3/cs_phpDB.class.php 2009-08-20 20:39:35 UTC (rev 127) @@ -0,0 +1,197 @@ +<?php + +/* + * A class for generic PostgreSQL database access. + * + * SVN INFORMATION::: + * SVN Signature:::::::: $Id$ + * Last Committted Date: $Date$ + * Last Committed Path:: $HeadURL$ + * + */ + +/////////////////////// +// ORIGINATION INFO: +// Author: Trevin Chow (with contributions from Lee Pang, wle...@ho...) +// Email: t1...@ma... +// Date: February 21, 2000 +// Last Updated: August 14, 2001 +// +// Description: +// Abstracts both the php function calls and the server information to POSTGRES +// databases. Utilizes class variables to maintain connection information such +// as number of rows, result id of last operation, etc. +// +/////////////////////// + +require_once(dirname(__FILE__) ."/abstract/cs_webapplibs.abstract.class.php"); +require_once(dirname(__FILE__) ."/abstract/cs_phpDB.abstract.class.php"); + +class cs_phpDB extends cs_contentAbstract { + + private $dbLayerObj; + private $dbType; + public $connectParams = array(); + + //========================================================================= + public function __construct($type='pgsql') { + + if(strlen($type)) { + + require_once(dirname(__FILE__) .'/db_types/'. __CLASS__ .'__'. $type .'.class.php'); + $className = __CLASS__ .'__'. $type; + $this->dbLayerObj = new $className; + $this->dbType = $type; + + parent::__construct(); + + $this->isInitialized = TRUE; + } + else { + throw new exception(__METHOD__ .": failed to give a type (". $type .")"); + } + }//end __construct() + //========================================================================= + + + + //========================================================================= + /** + * Magic method to call methods within the database abstraction layer ($this->dbLayerObj). + */ + public function __call($methodName, $args) { + if(method_exists($this->dbLayerObj, $methodName)) { + if($methodName == 'connect' && is_array($args[0])) { + //capture the connection parameters. + $this->connectParams = $args[0]; + } + $retval = call_user_func_array(array($this->dbLayerObj, $methodName), $args); + } + else { + throw new exception(__METHOD__ .': unsupported method ('. $methodName .') for database of type ('. $this->dbType .')'); + } + return($retval); + }//end __call() + //========================================================================= + + + + //========================================================================= + public function get_dbtype() { + return($this->dbType); + }//end get_dbtype() + //========================================================================= + + + + //========================================================================= + /** + * Performs queries which require results. Passing $indexField returns a + * complex array indexed from that field; passing $valueField will change + * it to a name=>value formatted array. + * + * NOTE:: when using an index field, be sure it is guaranteed to be unique, + * i.e. it is a primary key! If duplicates are found, the database class + * will throw an exception! + */ + public function run_query($sql, $indexField=null, $valueField=null) { + + $retval = array(); + + //length must be 19 as that's about the shortest valid SQL: "select * from table" + if(strlen($sql) >= 19) { + $this->exec($sql); + + $numRows = $this->numRows(); + $dbError = $this->errorMsg(); + if($numRows > 0 && !strlen($dbError)) { + if(strlen($indexField) && (is_null($valueField) || !strlen($valueField))) { + //return a complex array based on a given field. + $retval = $this->farray_fieldnames($indexField, null, 0); + } + elseif(strlen($indexField) && strlen($valueField)) { + //return an array as name=>value pairs. + $retval = $this->farray_nvp($indexField, $valueField); + } + else { + $retval = $this->farray_fieldnames(); + } + } + elseif($numRows == 0 && !strlen($dbError)) { + $retval = false; + } + else { + throw new exception(__METHOD__ .": no rows (". $numRows .") or dbError::: ". $dbError ."<BR>\nSQL::: ". $sql); + } + } + else { + throw new exception(__METHOD__ .": invalid length SQL (". $sql .")"); + } + + return($retval); + }//end run_query() + //========================================================================= + + + + //========================================================================= + /** + * Handles performing the insert statement & returning the last inserted ID. + */ + public function run_insert($sql, $sequence='null') { + + $this->exec($sql); + + if($this->numAffected() == 1 && !strlen($this->errorMsg())) { + //retrieve the ID just created. + $retval = $this->lastID($sequence); + } + else { + //something broke... + throw new exception(__METHOD__ .": failed to insert, rows=(". $this->numRows .")... " + ."ERROR::: ". $this->errorMsg() ."\n -- SQL:::: ". $sql); + } + + return($retval); + }//end run_insert() + //========================================================================= + + + + //========================================================================= + /** + * Performs the update & returns how many rows were affected. + */ + public function run_update($sql, $zeroIsOk=false) { + $this->exec($sql); + + $dberror = $this->errorMsg(); + $numAffected = $this->numAffected(); + + if(strlen($dberror)) { + throw new exception(__METHOD__ .": error while running update::: ". $dberror ." -- SQL::: ". $sql); + } + elseif($numAffected==0 && $zeroIsOk == false) { + throw new exception(__METHOD__ .": no rows updated (". $numAffected ."), SQL::: ". $sql); + } + + return($numAffected); + }//end run_update() + //========================================================================= + + + + //========================================================================= + public function reconnect() { + if(is_array($this->connectParams) && count($this->connectParams)) { + $this->dbLayerObj->connect($this->connectParams, true); + } + else { + throw new exception(__METHOD__ .": no connection parameters stored"); + } + }//end reconnect() + //========================================================================= + +} // end class phpDB + +?> Property changes on: trunk/0.3/cs_phpDB.class.php ___________________________________________________________________ Added: svn:keywords + Id Author Revision HeadURL Date Added: trunk/0.3/cs_sessionDB.class.php =================================================================== --- trunk/0.3/cs_sessionDB.class.php (rev 0) +++ trunk/0.3/cs_sessionDB.class.php 2009-08-20 20:39:35 UTC (rev 127) @@ -0,0 +1,366 @@ +<?php +/* + * FILE INFORMATION: + * $HeadURL$ + * $Id$ + * $LastChangedDate$ + * $LastChangedBy$ + * $LastChangedRevision$ + */ + +require_once(constant('LIBDIR') .'/cs-content/cs_session.class.php'); +require_once(dirname(__FILE__) .'/cs_phpDB.class.php'); +require_once(constant('LIBDIR') .'/cs-phpxml/cs_arrayToPath.class.php'); +require_once(constant('LIBDIR') .'/cs-webapplibs/cs_webdblogger.class.php'); + +class cs_sessionDB extends cs_session { + + protected $db; + + protected $logger = null; + + protected $logCategory = "DB Sessions"; + + //------------------------------------------------------------------------- + /** + * The constructor. + * + * @param $createSession (mixed,optional) determines if a session will be started or not; if + * this parameter is non-null and non-numeric, the value will be + * used as the session name. + */ + function __construct() { + + + //map some constants to connection parameters. + //NOTE::: all constants should be prefixed... + $constantPrefix = 'SESSION_DB_'; + $params = array('host', 'port', 'dbname', 'user', 'password'); + foreach($params as $name) { + $value = null; + $constantName = $constantPrefix . strtoupper($name); + if(defined($constantName)) { + $value = constant($constantName); + } + $dbParams[$name] = $value; + } + $this->db = new cs_phpDB(constant('DBTYPE')); + $this->db->connect($dbParams); + + $this->tableName = 'cs_session_store_table'; + $this->tablePKey = 'session_store_id'; + $this->sequenceName = 'cs_session_store_table_session_store_id_seq'; + + if(!$this->sessdb_table_exists()) { + $this->load_table(); + } + + //now tell PHP to use this class's methods for saving the session. + session_set_save_handler( + array(&$this, 'sessdb_open'), + array(&$this, 'sessdb_close'), + array(&$this, 'sessdb_read'), + array(&$this, 'sessdb_write'), + array(&$this, 'sessdb_destroy'), + array(&$this, 'sessdb_gc') + ); + + //NOTE::: calling session_id() here, prior to parent's construct, can set a specific session_id; if + // something like cs_authToken (part of cs-webapplibs project) were used, just call + // cs_authToken::create_token() here... + + parent::__construct(true); + + //Stop things from going into an audit log... see + //http://www.developertutorials.com/tutorials/php/saving-php-session-data-database-050711/page3.html + // NOTE::: not sure if this is valid or not... + $this->audit_logging = false; + + }//end __construct() + //------------------------------------------------------------------------- + + + + //------------------------------------------------------------------------- + /** + * Determines if the appropriate table exists in the database. + */ + public function sessdb_table_exists() { + try { + $test = $this->db->run_query("SELECT * FROM ". $this->tableName . + " ORDER BY ". $this->tablePKey ." LIMIT 1"); + $exists = true; + } + catch(exception $e) { + $this->exception_handler(__METHOD__ .": exception while trying to detect table::: ". $e->getMessage()); + $exists = false; + } + + return($exists); + }//end sessdb_table_exists() + //------------------------------------------------------------------------- + + + + //------------------------------------------------------------------------- + private function load_table() { + $filename = dirname(__FILE__) .'/schema/db_session_schema.'. $this->db->get_dbtype() .'.sql'; + if(file_exists($filename)) { + try { + $this->db->run_update(file_get_contents($filename),true); + } + catch(exception $e) { + $this->exception_handler(__METHOD__ .": failed to load required table " . + "into your database automatically::: ". $e->getMessage(), true); + } + } + else { + $this->exception_handler(__METHOD__ .": while attempting to load required " . + "table into your database, discovered you have a missing schema " . + "file (". $filename .")", true); + } + }//end load_table() + //------------------------------------------------------------------------- + + + + //------------------------------------------------------------------------- + protected function is_valid_sid($sid) { + $isValid = false; + if(strlen($sid) == 32) { + try { + $sql = "SELECT * FROM ". $this->tableName ." WHERE session_id='". + $sid ."'"; + $this->db->run_query($sql); + $numrows = $this->db->numRows(); + if($numrows == 1) { + $isValid = true; + } + elseif($numrows > 0 || $numrows < 0) { + $this->exception_handler(__METHOD__ .": invalid numrows returned (". $numrows .")",true); + } + } + catch(exception $e) { + //well... do nothing I guess. + } + } + + return($isValid); + }//end is_valid_sid() + //------------------------------------------------------------------------- + + + + //------------------------------------------------------------------------- + /** + * Open the session (doesn't really do anything) + */ + public function sessdb_open($savePath, $sessionName) { + return(true); + }//end sessdb_open() + //------------------------------------------------------------------------- + + + + //------------------------------------------------------------------------- + /** + * Close the session (call the "gc" method) + */ + public function sessdb_close() { + return($this->sessdb_gc(0)); + }//end sessdb_close() + //------------------------------------------------------------------------- + + + + //------------------------------------------------------------------------- + /** + * Read information about the session. If there is no data, it MUST return + * an empty string instead of NULL. + */ + public function sessdb_read($sid) { + $retval = ''; + try { + $sql = "SELECT * FROM ". $this->tableName ." WHERE session_id='". + $sid ."'"; + $data = $this->db->run_query($sql); + + if($this->db->numRows() == 1) { + $retval = $data['session_data']; + } + } + catch(exception $e) { + //no throwing exceptions... + $this->exception_handler(__METHOD__ .": failed to read::: ". $e->getMessage()); + } + return($retval); + }//end sessdb_read() + //------------------------------------------------------------------------- + + + + //------------------------------------------------------------------------- + public function sessdb_write($sid, $data) { + $data = array( + 'session_data' => $data, + 'user_id' => null + ); + $cleanString = array( + 'session_data' => 'sql', + 'user_id' => 'numeric' + ); + + + + //pull the uid out of the session... + if(defined('SESSION_DBSAVE_UIDPATH')) { + $a2p = new cs_arrayToPath($_SESSION); + $uidVal = $a2p->get_data(constant('SESSION_DBSAVE_UIDPATH')); + + if(is_string($uidVal) || is_numeric($uidVal)) { + $data['user_id'] = $uidVal; + } + } + + $afterSql = ""; + if($this->is_valid_sid($sid)) { + $type = 'update'; + $sql = "UPDATE ". $this->tableName ." SET "; + $afterSql = "WHERE session_id='". $sid ."'"; + $data['last_updated'] = 'NOW()'; + $secondArg = false; + } + else { + $type = 'insert'; + $sql = "INSERT INTO ". $this->tableName ." "; + $data['session_id'] = $sid; + $secondArg = $this->sequenceName; + } + + $sql .= $this->gfObj->string_from_array($data, $type, null, $cleanString) .' '. $afterSql; + try { + $funcName = 'run_'. $type; + $res = $this->db->$funcName($sql, $secondArg); + } + catch(exception $e) { + //umm... yeah. + $this->exception_handler(__METHOD__ .": failed to perform action (". $type .")::: ". $e->getMessage()); + } + + return(true); + }//end sessdb_write() + //------------------------------------------------------------------------- + + + + //------------------------------------------------------------------------- + public function sessdb_destroy($sid) { + try { + $sql = "DELETE FROM ". $this->tableName ." WHERE session_id='". $sid ."'"; + $numDeleted = $this->db->run_update($sql, true); + + if($numDeleted > 0) { + $this->do_log("Destroyed session_id (". $sid .")", 'deleted'); + } + } + catch(exception $e) { + //do... nothing? + } + return(true); + }//end sessdb_destroy() + //------------------------------------------------------------------------- + + + + //------------------------------------------------------------------------- + /** + * Define maximum lifetime (in seconds) to store sessions in the database. + * Anything that is older than that time will be purged (gc='garbage collector'). + */ + public function sessdb_gc($maxLifetime=null) { + + $dateFormat = 'Y-m-d H:i:s'; + $strftimeFormat = '%Y-%m-%d %H:%M:%S'; + $nowTime = date($dateFormat); + $excludeCurrent = true; + if(defined('SESSION_MAX_TIME') || defined('SESSION_MAX_IDLE')) { + $maxFreshness = null; + if(defined('SESSION_MAX_TIME')) { + $date = strtotime('- '. constant('SESSION_MAX_TIME')); + $maxFreshness = "date_created < '". strftime($strftimeFormat, $date) ."'"; + $excludeCurrent=false; + } + if(defined('SESSION_MAX_IDLE')) { + + $date = strtotime('- '. constant('SESSION_MAX_IDLE')); + $addThis = "last_updated < '". strftime($strftimeFormat, $date) ."'"; + $maxFreshness = $this->gfObj->create_list($maxFreshness, $addThis, ' OR '); + } + } + elseif(is_null($maxLifetime) || !is_numeric($maxLifetime) || $maxLifetime <= 0) { + //pull it from PHP's ini settings. + $maxLifetime = ini_get("session.gc_maxlifetime"); + $interval = $maxLifetime .' seconds'; + + $dt1 = strtotime($nowTime .' - '. $interval); + $maxFreshness = "last_updated < '". date($dateFormat, $dt1) ."'"; + } + + + + try { + //destroy old sessions, but don't complain if nothing is deleted. + $sql = "DELETE FROM ". $this->tableName ." WHERE ". $maxFreshness; + if(strlen($this->sid) && $excludeCurrent === false) { + $sql .= " AND session_id != '". $this->sid ."'"; + } + $numCleaned = $this->db->run_update($sql, true); + + if($numCleaned > 0) { + $this->do_log("cleaned (". $numCleaned .") old sessions, " . + "excludeCurrent=(". $this->gfObj->interpret_bool($excludeCurrent) .")" . + ", maxFreshness=(". $maxFreshness .")", "debug"); + } + } + catch(exception $e) { + $this->exception_handler(__METHOD__ .": exception while cleaning: ". $e->getMessage()); + } + + return(true); + + }//end sessdb_gc() + //------------------------------------------------------------------------- + + + + //------------------------------------------------------------------------- + protected function do_log($message, $type) { + + //check if the logger object has been created. + if(!is_object($this->logger)) { + $newDB = new cs_phpDB(constant('DBTYPE')); + $newDB->connect($this->db->connectParams, true); + $this->logger = new cs_webdblogger($newDB, $this->logCategory); + } + + return($this->logger->log_by_class("SID=(". $this->sid .") -- ". $message,$type)); + + }//end do_log() + //------------------------------------------------------------------------- + + + + //------------------------------------------------------------------------- + protected function exception_handler($message, $throwException=false) { + $logId = $this->do_log($message, 'exception in code'); + if($throwException === true) { + //in this class, it is mostly useless to throw exceptions, so by default they're not thrown. + throw new exception($message); + } + return($logId); + }//end exception_handler() + //------------------------------------------------------------------------- + + +}//end cs_session{} +?> \ No newline at end of file Property changes on: trunk/0.3/cs_sessionDB.class.php ___________________________________________________________________ Added: svn:executable + * Added: svn:keywords + Id Author Revision HeadURL Date Added: trunk/0.3/cs_siteConfig.class.php =================================================================== --- trunk/0.3/cs_siteConfig.class.php (rev 0) +++ trunk/0.3/cs_siteConfig.class.php 2009-08-20 20:39:35 UTC (rev 127) @@ -0,0 +1,404 @@ +<?php + +/* + * A class for handling configuration of database-driven web applications. + * + * NOTICE::: this class requires that cs-phpxml and cs-arraytopath are both available + * at the same directory level as cs-content; all projects are SourceForge.net projects, + * using their unix names ("cs-phpxml" and "cs-arrayToPath"). The cs-phpxml project + * requires cs-arrayToPath for parsing XML paths. + * + * SVN INFORMATION::: + * SVN Signature:::::::: $Id$ + * Last Committted Date: $Date$ + * Last Committed Path:: $HeadURL$ + * + */ + +require_once(dirname(__FILE__) .'/../cs-content/abstract/cs_content.abstract.class.php'); +require_once(dirname(__FILE__) .'/../cs-content/cs_fileSystem.class.php'); +require_once(dirname(__FILE__). '/../cs-phpxml/cs_phpxmlParser.class.php'); +require_once(dirname(__FILE__) .'/../cs-phpxml/cs_phpxmlBuilder.class.php'); + +class cs_siteConfig extends cs_contentAbstract { + + /** XMLParser{} object, for reading XML config file. */ + private $xmlReader; + + /** cs_fileSystem{} object, for writing/updating XML config file + * (only available if file is writable) + */ + private $xmlWriter; + + /** XMLBuilder{} object, for updating XML. */ + private $xmlBuilder; + + /** cs_fileSystem{} object, for handling generic file operations (i.e. reading) */ + private $fs; + + /** boolean flag indicating if the given config file is readOnly (false=read/write) */ + private $readOnly; + + /** Directory for the config file. */ + private $configDirname; + + /** Location of the configuration file itself. */ + private $configFile; + + /** Active section of the full site configuration. */ + private $activeSection; + + /** The FULL configuration file, instead of just the active section. */ + private $fullConfig=array(); + + /** cs_arrayToPath{} object. */ + private $a2p; + + /** Prefix to add to every index in GLOBALS and CONSTANTS. */ + private $setVarPrefix; + + /** Sections available within the config */ + private $configSections=array(); + + /** Boolean flag to determine if the object has been properly initialized or not. */ + private $isInitialized=false; + + /** Store a list of items that need to be pushed into $GLOBALS on a given path. */ + private $setGlobalArrays=array(); + + //------------------------------------------------------------------------- + /** + * Constructor. + * + * @param $configFileLocation (str) URI for config file. + * @param $section (str,optional) set active section (default=MAIN) + * @param $setVarPrefix (str,optional) prefix to add to all global & constant names. + * + * @return NULL (PASS) object successfully created + * @return exception (FAIL) failed to create object (see exception message) + */ + public function __construct($configFileLocation, $section='MAIN', $setVarPrefix=null) { + + $section = strtoupper($section); + $this->setVarPrefix=$setVarPrefix; + + parent::__construct(); + + if(strlen($configFileLocation) && file_exists($configFileLocation)) { + + $this->configDirname = dirname($configFileLocation); + $this->configFile = $configFileLocation; + $this->fs = new cs_fileSystem($this->configDirname); + + $this->xmlReader = new cs_phpxmlParser($this->fs->read($configFileLocation)); + + if($this->fs->is_writable($configFileLocation)) { + $this->readOnly = false; + $this->xmlWriter = new cs_fileSystem($this->configDirname); + + } + else { + $this->readOnly = true; + } + } + else { + throw new exception(__METHOD__ .": invalid configuration file (". $configFileLocation .")"); + } + + if(strlen($section)) { + try { + $this->parse_config(); + $this->set_active_section($section); + $this->config = $this->get_section($section); + } + catch(exception $e) { + throw new exception(__METHOD__ .": invalid section (". $section ."), DETAILS::: ". $e->getMessage()); + } + } + else { + throw new exception(__METHOD__ .": no section given (". $section .")"); + } + + }//end __construct() + //------------------------------------------------------------------------- + + + + //------------------------------------------------------------------------- + /** + * Sets the active section. + * + * @param $section (str) section to be set as active. + * + * @return VOID (PASS) section was set successfully. + * @return exception (FAIL) problem encountred setting section. + */ + public function set_active_section($section) { + if($this->isInitialized === true) { + $section = strtoupper($section); + if(in_array($section, $this->configSections)) { + $this->activeSection = $section; + } + else { + throw new exception(__METHOD__ .": invalid section (". $section .")"); + } + } + else { + throw new exception(__METHOD__ .": not initialized"); + } + }//end set_active_section($section) + //------------------------------------------------------------------------- + + + + //------------------------------------------------------------------------- + /** + * Parse the configuration file. Handles replacing {VARIABLES} in values, + * sets items as global or as constants, and creates array indicating the + * available sections from the config file. + * + * @param VOID (void) no arguments accepted. + * + * @return NULL (PASS) successfully parsed configuration + * @return exception (FAIL) exception indicates problem encountered. + */ + private function parse_config() { + if(is_object($this->xmlReader)) { + $data = $this->xmlReader->get_path($this->xmlReader->get_root_element()); + $specialVars = $this->build_special_vars(); + $parseThis = array(); + + + $this->configSections = array(); + + foreach($data as $section=>$secData) { + //only handle UPPERCASE index names; lowercase indexes are special entries (i.e. "type" or "attributes" + if($section == strtoupper($section)) { + $this->configSections[] = $section; + + unset($secData['type']); + + if(isset($secData['attributes']) && is_array($secData['attributes'])) { + $sectionAttribs = $secData['attributes']; + unset($secData['attributes']); + + //put stuff into the globals scope... + if(isset($sectionAttribs['SETGLOBAL'])) { + $path = $section; + + $setPath = $path; + if(strlen($sectionAttribs['GLOBALARRAYLOCATION'])) { + $setPath = $sectionAttribs['GLOBALARRAYLOCATION']; + } + $this->setGlobalArrays[$path] = $setPath; + } + } + + foreach($secData as $itemName=>$itemValue) { + $attribs = array(); + if(isset($itemValue['attributes']) && is_array($itemValue['attributes'])) { + $attribs = $itemValue['attributes']; + } + if(isset($itemValue['value'])) { + $itemValue = $itemValue['value']; + } + else { + $itemValue = null; + } + if(preg_match("/{/", $itemValue)) { + $origVal = $itemValue; + + //remove double-slashes (//) + $itemValue = preg_replace('/[\/]{2,}/', '\/', $itemValue); + + //remove leading slash for string replaces (i.e. "{/MAIN/SITE_ROOT}" becomes "{MAIN/SITE_ROOT}") + $itemValue = preg_replace('/{\//', '{', $itemValue); + + //replace special vars. + $itemValue = $this->gfObj->mini_parser($itemValue, $specialVars, '{', '}'); + + //replace internal vars. + $itemValue = $this->gfObj->mini_parser($itemValue, $parseThis, '{', '}'); + } + + if(isset($attribs['CLEANPATH'])) { + $itemValue = $this->fs->resolve_path_with_dots($itemValue); + } + + $parseThis[$itemName] = $itemValue; + $parseThis[$section ."/". $itemName] = $itemValue; + $data[$section][$itemName]['value'] = $itemValue; + + $setVarIndex = $this->setVarPrefix . $itemName; + if(isset($attribs['SETGLOBAL'])) { + $GLOBALS[$setVarIndex] = $itemValue; + } + if(isset($attribs['SETCONSTANT'])) { + if(isset($attribs['SETCONSTANTPREFIX'])) { + //did they give a specific prefix, or just a number/true? + if(strlen($attribs['SETCONSTANTPREFIX']) == 1) { + $setVarIndex = $section ."-". $setVarIndex; + } + else { + //use the prefix they gave. + $setVarIndex = $attribs['SETCONSTANTPREFIX'] ."-". $setVarIndex; + } + } + if(!defined($setVarIndex)) { + define($setVarIndex, $itemValue); + } + } + } + } + } + + $this->a2p = new cs_arrayToPath($data); + $this->isInitialized=true; + + if(count($this->setGlobalArrays)) { + $globA2p = new cs_arrayToPath(&$GLOBALS); + foreach($this->setGlobalArrays as $configPath=>$globalsPath) { + if($this->a2p->get_data($configPath)) { + $setMe = array(); + foreach($this->a2p->get_data($configPath) as $i=>$v) { + $setMe[$i] = $v['value']; + } + $globA2p->set_data($globalsPath, $setMe); + } + else { + throw new exception(__METHOD__ .": attempted to set global array from non-existent path (". $configPath .")"); + } + } + } + } + else { + throw new exception(__METHOD__ .": xmlReader not created, object probably not initialized"); + } + }//end parse_config() + //------------------------------------------------------------------------- + + + + //------------------------------------------------------------------------- + /** + * Retrieve all data about the given section. + * + * @param $section (str) section to retrieve. + * + * @return array (PASS) array contains section data. + * @return exception (FAIL) exception indicates problem. + */ + public function get_section($section) { + if($this->isInitialized === true) { + $section = strtoupper($section); + $data = $this->a2p->get_data($section); + + if(is_array($data) && count($data) && $data['type'] == 'open') { + unset($data['type']); + $retval = $data; + } + else { + throw new exception(__METHOD__ .": invalid section (". $section .") or no data (". $data['type'] .")"); + } + } + else { + throw new exception(__METHOD__ .": not initialized"); + } + + return($retval); + }//end get_section() + //------------------------------------------------------------------------- + + + + //------------------------------------------------------------------------- + /** + * Retrieves value from the active section, or from another (other sections + * specified like "SECTION/INDEX"). + * + * @param $index (str) index name of value to retrieve. + * + * @return mixed (PASS) returns value of given index. + * + * NOTE::: this will return NULL if the given index or section/index does + * not exist. + */ + public function get_value($index) { + if($this->isInitialized === true) { + if(preg_match("/\//", $index)) { + //section NOT given, assume they're looking for something in the active section. + $index = $this->activeSection ."/". $index; + } + $retval = $this->a2p->get_data($index .'/value'); + } + else { + throw new exception(__METHOD__ .": not initialized"); + } + return($retval); + }//end get_value() + //------------------------------------------------------------------------- + + + + //------------------------------------------------------------------------- + /** + * Retrieves list of valid configuration sections, as defined by + * parse_config(). + * + * @param VOID (void) no parameters accepted. + * + * @return array (PASS) array holds list of valid sections. + * @return exception (FAIL) exception gives error. + */ + public function get_valid_sections() { + if($this->isInitialized === true) { + if(is_array($this->configSections) && count($this->configSections)) { + $retval = $this->configSections; + } + else { + throw new exception(__METHOD__ .": no sections defined, probably invalid configuration"); + } + } + else { + throw new exception(__METHOD__ .": not initialized"); + } + + return($retval); + }//end get_valid_sections() + //------------------------------------------------------------------------- + + + + //------------------------------------------------------------------------- + private function build_special_vars() { + //determine the current "APPURL" (current URL minus hostname and current filename) + { + $appUrl = $_SERVER['SCRIPT_NAME']; + $bits = explode('/', $appUrl); + if(!strlen($bits[0])) { + array_shift($bits); + } + if(count($bits)) { + array_pop($bits); + } + if(!count($bits)) { + $appUrl = '/'; + } + else { + $appUrl = '/'. $this->gfObj->string_from_array($bits, null, '/'); + } + } + + $specialVars = array( + '_DIRNAMEOFFILE_' => $this->configDirname, + '_CONFIGFILE_' => $this->configFile, + '_THISFILE_' => $this->configFile, + '_APPURL_' => $appUrl + ); + return($specialVars); + }//end build_special_vars() + //------------------------------------------------------------------------- + +}//end cs_siteConfig + +?> Property changes on: trunk/0.3/cs_siteConfig.class.php ___________________________________________________________________ Added: svn:keywords + Id Author Revision HeadURL Date Added: trunk/0.3/cs_tabs.class.php =================================================================== --- trunk/0.3/cs_tabs.class.php (rev 0) +++ trunk/0.3/cs_tabs.class.php 2009-08-20 20:39:35 UTC (rev 127) @@ -0,0 +1,175 @@ +<?php +/* + * Created on Jan 9, 2007 + * + */ + +require_once(dirname(__FILE__) .'/abstract/cs_content.abstract.class.php'); + + +class cs_tabs extends cs_contentAbstract { + private $tabsArr=array(); + private $selectedTab; + + private $templateVar; + private $gfObj; + + /** This is the default suffix to use when none is given during the add_tab() call. */ + private $defaultSuffix='tab'; + + //--------------------------------------------------------------------------------------------- + /** + * Build the object, and parses the given template. Tabs must be added & selected manually. + * + * @param $csPageObj (object) Instance of the class "cs_genericPage". + * @param $templateVar (str,optional) What template var to find the tab blockrows in. + */ + public function __construct($templateVar="tabs") { + parent::__construct(false); + + if(is_object($templateVar)) { + //trying to pass cs_genericPage{}... tell 'em we don't like that anymore. + throw new exception(__METHOD__ .": got an object (". get_class($templateVar) .") instead of template var name"); + } + elseif(is_string($templateVar) && is_null($templateVar) || strlen($templateVar) < 3) { + //no template name? AHH!!! + throw new exception("cs_tabs::__construct(): failed to specify proper template file"); + } + else { + //set the internal var. + $this->templateVar = $templateVar; + } + + $this->gfObj = new cs_globalFunctions; + }//end __construct() + //--------------------------------------------------------------------------------------------- + + + + //--------------------------------------------------------------------------------------------- + public function add_tab_array(array $tabs, $useSuffix=null) { + $retval = 0; + foreach($tabs as $name=>$url) { + //call an internal method to do it. + $retval += $this->add_tab($name, $url, $useSuffix); + } + + return($retval); + }//end add_tab_array() + //--------------------------------------------------------------------------------------------- + + + + //--------------------------------------------------------------------------------------------- + /** + * Sets the given tab as selected, provided it exists. + * + * @param $tabName (str) Sets this tab as selected. + * @return (void) + */ + public function select_tab($tabName) { + $this->selectedTab = $tabName; + }//end select_tab() + //--------------------------------------------------------------------------------------------- + + + + //--------------------------------------------------------------------------------------------- + public function add_tab($tabName, $url, $useSuffix=null) { + + //set the default suffix. + if(is_null($useSuffix)) { + $useSuffix = $this->defaultSuffix; + } + + //add it to an array. + $this->tabsArr[$tabName] = array( + 'url' => $url, + 'suffix' => $useSuffix + ); + }//end add_tab() + //--------------------------------------------------------------------------------------------- + + + + //--------------------------------------------------------------------------------------------- + /** + * Call this to add the parsed tabs into the page. + */ + public function display_tabs(array $blockRows) { + + if(!strlen($this->selectedTab)) { + $keys = array_keys($this->tabsArr); + $this->select_tab($keys[0]); + } + + if(is_array($this->tabsArr) && count($this->tabsArr)) { + $finalString = ""; + //loop through the array. + foreach($this->tabsArr as $tabName=>$tabData) { + + $url = $tabData['url']; + $suffix = $tabData['suffix']; + + $blockRowName = 'unselected_'. $suffix; + if(strtolower($tabName) == strtolower($this->selectedTab)) { + $blockRowName = 'selected_'. $suffix; + } + + if(isset($blockRows[$blockRowName])) { + $useTabContent = $blockRows[$blockRowName]; + } + else { + throw new exception(__METHOD__ ."(): failed to load block row " . + "(". $blockRowName .") for tab (". $tabName .")". + $this->gfObj->debug_print($blockRows,0)); + } + + $parseThis = array( + 'title' => $tabName, + 'url' => $url, + 'cleanTitle' => preg_replace('/[^a-zA-Z0-9]/', '_', $tabName) + ); + $finalString .= $this->gfObj->mini_parser($useTabContent, $parseThis, '%%', '%%'); + } + } + else { + //something bombed. + throw new exception(__METHOD__ ."(): no tabs to add"); + } + + return($finalString); + }//end display_tabs() + //--------------------------------------------------------------------------------------------- + + + //--------------------------------------------------------------------------------------------- + /** + * Determine if the given named tab exists (returns boolean true/false) + */ + public function tab_exists($tabName) { + $retval = false; + if(isset($this->tabsArr[$tabName])) { + $retval = true; + } + return($retval); + }//end tab_exists() + //--------------------------------------------------------------------------------------------- + + + + //--------------------------------------------------------------------------------------------- + public function rename_tab($tabName, $newTabName) { + if($this->tab_exists($tabName) && !$this->tab_exists($newTabName)) { + $tabContents = $this->tabsArr[$tabName]; + unset($this->tabsArr[$tabName]); + $this->tabsArr[$newTabName] = $tabContents; + } + else { + throw new exception(__METHOD__ .": tried to rename non-existent tab (". $tabName .") to (". $newTabName .")"); + } + }//end rename_tab(); + //--------------------------------------------------------------------------------------------- + +} +?> Property changes on: trunk/0.3/cs_tabs.class.php ___________________________________________________________________ Added: svn:keywords + Id Author Revision HeadURL Date Modified: trunk/0.3/cs_webdbupgrade.class.php =================================================================== --- trunk/0.3/cs_webdbupgrade.class.php 2009-08-20 19:04:39 UTC (rev 126) +++ trunk/0.3/cs_webdbupgrade.class.php 2009-08-20 20:39:35 UTC (rev 127) @@ -13,7 +13,8 @@ */ require_once(dirname(__FILE__) .'/abstract/cs_webapplibs.abstract.class.php'); - require_once(dirname(__FILE__) .'/cs_webdblogger.class.php'); +require_once(dirname(__FILE__) .'/cs_webdblogger.class.php'); +require_once(dirname(__FILE__) .'/cs_phpDB.class.php'); class cs_webdbupgrade extends cs_webapplibsAbstract { @@ -88,7 +89,6 @@ require_once(constant('LIBDIR') .'/cs-content/cs_globalFunctions.class.php'); require_once(constant('LIBDIR') .'/cs-content/cs_fileSystem.class.php'); - require_once(constant('LIBDIR') .'/cs-content/cs_phpDB.class.php'); require_once(constant('LIBDIR') .'/cs-phpxml/cs_phpxmlParser.class.php'); require_once(constant('LIBDIR') .'/cs-phpxml/cs_phpxmlCreator.class.php'); require_once(constant('LIBDIR') .'/cs-phpxml/cs_arrayToPath.class.php'); Added: trunk/0.3/db_types/cs_phpDB__mysql.class.php =================================================================== --- trunk/0.3/db_types/cs_phpDB__mysql.class.php (rev 0) +++ trunk/0.3/db_types/cs_phpDB__mysql.class.php 2009-08-20 20:39:35 UTC (rev 127) @@ -0,0 +1,821 @@ +<?php + +/* + * A class for generic MySQL database access. + * + * SVN INFORMATION::: + * SVN Signature:::::::: $Id$ + * Last Committted Date: $Date$ + * Last Committed Path:: $HeadURL$ + * + */ + + +class cs_phpDB__mysql extends cs_phpDBAbstract { + + /** Internal result set pointer. */ + protected $result = NULL; + + /** Internal error code. */ + protected $errorCode = 0; + + /** Status of the current transaction. */ + protected $transStatus = NULL; + + /** Whether there is a transaction in progress or not. */ + protected $inTrans = FALSE; + + /** Holds the last query performed. */ + protected $lastQuery = NULL; + + /** List of queries that have been run */ + protected $queryList=array(); + + /** How many seconds to wait for a query before cancelling it. */ + protected $timeOutSeconds = NULL; + + /** Internal check to determine if a connection has been established. */ + protected $isConnected=FALSE; + + /** Internal check to determine if the parameters have been set. */ + protected $paramsAreSet=FALSE; + + /** Resource handle. */ + protected $connectionID = -1; + + /** Hostname or IP to connect to */ + protected $host; + + /** Port to connect to (default for Postgres is 5432) */ + protected $port; + + /** Name of the database */ + protected $dbname; + + /** Username to connect to the database */ + protected $user; + + /** password to connect to the database */ + protected $password; + + /** Row counter for looping through records */ + protected $row = -1; + + /** cs_globalFunctions object, for string stuff. */ + protected $gfObj; + + /** Internal check to ensure the object has been properly created. */ + protected $isInitialized=FALSE; + + /** List of prepared statements, indexed off the name, with the sub-array being fieldname=>dataType. */ + protected $preparedStatements = array(); + + /** Set to TRUE to save all queries into an array. */ + protected $useQueryList=FALSE; + + /** array that essentially remembers how many times beginTrans() was called. */ + protected $transactionTree = NULL; + + //////////////////////////////////////////// + // Core primary connection/database function + //////////////////////////////////////////// + + + //========================================================================= + public function __construct() { + parent::__construct(); + }//end __construct() + //========================================================================= + + + + //========================================================================= + /** + * Set appropriate parameters for database connection + */ + public function set_db_info(array $params){ + $this->sanity_check(); + $required = array('host', 'dbname', 'user', 'password'); + + $requiredCount = 0; + foreach($params as $index=>$value) { + if(property_exists($this, $index) && in_array($index, $required)) { + $this->$index = $value; + $requiredCount++; + } + else { + throw new exception(__METHOD__. ": property (". $index .") does " . + "not exist or isn't allowed"); + } + } + + if($requiredCount == count($required)) { + $this->paramsAreSet = TRUE; + } + else { + throw new exception(__METHOD__ .": required count (". $requiredCount + .") does not match required number of fields (". count($required) .")"); + } + }//end set_db_info() + //========================================================================= + + + + //========================================================================= + /** + * Standard method to close connection. + */ + function close() { + $this->isConnected = FALSE; + $retval = null; + if($this->connectionID != -1) { + $retval = mysql_close($this->connectionID); + $this->transStatus = null; + $this->inTrans=null; + $this->transactionTree=null; + } + else { + throw new exception(__METHOD__ .": Failed to close connection: connection is invalid"); + } + + return($retval); + }//end close() + //========================================================================= + + + + //========================================================================= + /** + * Connect to the database + */ + function connect(array $dbParams=NULL, $forceNewConnection=FALSE){ + $this->sanity_check(); + $retval = NULL; + if(is_array($dbParams)) { + $this->set_db_info($dbParams); + } + + if($this->paramsAreSet === TRUE) { + + //start output buffer for displaying error. + ob_start(); + $connID = mysql_connect($this->host, $this->user, $this->password, $forceNewConnection); + if(!$connID) { + $connectError = mysql_error(); + } + else { + mysql_select_db($this->dbname); + $connectError = ob_get_contents(); + } + ob_end_clean(); + + if(is_resource($connID)) { + $this->errorCode=0; + $this->connectionID = $connID; + $this->isConnected = TRUE; + $retval = $this->connectionID; + } + else { + if(is_bool($connID) && !strlen($connectError)) { + $connectError = "generic connection failure"; + } + throw new exception(__METHOD__ .": FATAL ERROR: ". $connectError); + } + } + else { + throw new exception(__METHOD__ .": paramsAreSet=(". $this->paramsAreSet ."), isConnected=(". $this->isConnected .")"); + } + + return($retval); + }//end connect() + //========================================================================= + + + + //========================================================================= + function get_hostname() { + $this->sanity_check(); + return($this->host); + }//end get_hostname() + //========================================================================= + + + + //========================================================================= + /** + * Run sql queries + * + * TODO: re-implement query logging (setting debug, logfilename, etc). + */ + function exec($query) { + $this->lastQuery = $query; + if($this->useQueryList) { + $this->queryList[] = $query; + } + $returnVal = false; + + $this->result = mysql_query($query, $this->connectionID); + + if($this->result !== false) { + if (eregi("^[[:space:]]*select", $query)) { + //If we didn't have an error and we are a select statement, move the pointer to first result + $numRows = $this->numRows(); + if($numRows > 0) { + $this->move_first(); + } + $returnVal = $numRows; + + } + else { + //We got something other than an update. Use numAffected + $returnVal = $this->numAffected(); + } + } + return($returnVal); + }//end exec() + //========================================================================= + + + + //========================================================================= + /** + * Returns any error caused by the last executed query. + * + * @return NULL OK: no error + * @return (string) FAIL: contains error returned from the query. + */ + function errorMsg($setMessage=NULL,$logError=NULL) { + $this->sanity_check(); + if ($this->connectionID < 0) { + //TODO: implement MySQL version (error codes may vary)... + switch ($this->errorCode) { + //############################################### + case -1: + $retVal = "FATAL ERROR - CONNECTION ERROR: RESOURCE NOT FOUND"; + break; + //############################################### + + //############################################### + case -2: + $retVal = "FATAL ERROR - CLASS ERROR: FUNCTION CALLED WITHOUT PARAMETERS"; + break; + //############################################### + + //############################################### + case -3: + $retVal = "Query exceeded maximum timeout (". $this->timeoutSeconds ."... [truncated message content] |