aliroDatabase.php

Go to the documentation of this file.
00001 <?php
00002 
00003 /*******************************************************************************
00004  * Aliro - the modern, accessible content management system
00005  *
00006  * Aliro is open source software, free to use, and licensed under GPL.
00007  * You can find the full licence at http://www.gnu.org/copyleft/gpl.html GNU/GPL
00008  *
00009  * The author freely draws attention to the fact that Aliro derives from Mambo,
00010  * software that is controlled by the Mambo Foundation.  However, this section
00011  * of code is totally new.  If it should contain any fragments that are similar
00012  * to Mambo, please bear in mind (1) there are only so many ways to do things
00013  * and (2) the author of Aliro is also the author and copyright owner for large
00014  * parts of Mambo 4.6.
00015  *
00016  * Tribute should be paid to all the developers who took Mambo to the stage
00017  * it had reached at the time Aliro was created.  It is a feature rich system
00018  * that contains a good deal of innovation.
00019  *
00020  * Your attention is also drawn to the fact that Aliro relies on other items of
00021  * open source software, which is very much in the spirit of open source.  Aliro
00022  * wishes to give credit to those items of code.  Please refer to
00023  * http://aliro.org/credits for details.  The credits are not included within
00024  * the Aliro package simply to avoid providing a marker that allows hackers to
00025  * identify the system.
00026  *
00027  * Copyright in this code is strictly reserved by its author, Martin Brampton.
00028  * If it seems appropriate, the copyright will be vested in the Aliro Organisation
00029  * at a suitable time.
00030  *
00031  * Copyright (c) 2007 Martin Brampton
00032  *
00033  * http://aliro.org
00034  *
00035  * counterpoint@aliro.org
00036  *
00037  * Everything here is to do with database management.
00038  *
00039  * aliroDataCache is not yet used - it exists ready for development into a cache
00040  * for database queries.  This has low priority or may even be abandonded, since
00041  * it is usually more effective to cache complete output, or more structured
00042  * data derived from the database, as happens in cached singletons.
00043  *
00044  * databaseException uses PHP5 exception handling for database errors, rather
00045  * than expecting other applications to handle them.  This is combined with the
00046  * introduction of an error logging table, since detailed diagnostic information
00047  * is useful to developers, but not much use to users.  Only basic messages are
00048  * shown to users.
00049  *
00050  * aliroAbstractDatabase contains all the basic functions to make it easier to
00051  * code database functions.  It uses the PHP5 mysqli interface.
00052  *
00053  * database is a class provided for backwards compatibility with Mambo 4.x and
00054  * Joomla! 1.0.x.  aliroDatabaseHandler is simply the preferred name for a class
00055  * with the same functions as "database".
00056  *
00057  * aliroDatabase is a singleton extension of the abstract database class.  It is
00058  * created from the stored credentials for the general database driving Aliro.
00059  *
00060  * aliroCoreDatabase is another singleton extension of the abstract database class.
00061  * It is the optionally separate database holding critical tables relating only to
00062  * the core of Aliro, such as information about menus, components, etc.  It is also
00063  * the only place where user passwords are stored, thus reducing the impact of
00064  * SQL injection attacks that penetrate only the general database.  If it is not
00065  * possible to have two databases, Aliro will run with both being the same.
00066  *
00067  * Other names are purely for compatibility and are deprecated.
00068  *
00069  */
00070 
00071 class aliroDataCache {
00072     public $records = array();
00073 }
00074 
00075 class databaseException extends Exception {
00076     public $dbname = '';
00077     public $sql = '';
00078     public $number = 0;
00079 
00080     public function __construct ($dbname, $message, $sql, $number, $dbtrace) {
00081         parent::__construct($message, $number);
00082         $this->dbname = $dbname;
00083         $this->sql = $sql;
00084         $this->dbtrace = $dbtrace;
00085     }
00086 
00087 }
00088 
00089 class databaseInterfaceFactory {
00090 
00091     public static function getInterface () {
00092         if (function_exists( 'mysqli_connect' )) return new mysqliInterface;
00093         if (function_exists( 'mysql_connect' )) return new mysqlInterface;
00094         return  null;
00095     }
00096 
00097 }
00098 
00099 abstract class aliroAbstractDatabase {
00100     protected static $stats = array();
00101     protected $_sql='';
00102     protected $_cached=false;
00103     protected $_errorNum=0;
00104     protected $_errorMsg='';
00105     protected $_table_prefix='';
00106     protected $_resource='';
00107     protected $_cursor=null;
00108     protected $_log=array();
00109     protected $DBname = '';
00110     protected $DBInfo = null;
00111     protected $cache = null;
00112     protected $interface = null;
00113 
00114     public function __construct( $host='localhost', $user, $pass, $db, $table_prefix, $return_on_error=false ) {
00115         // perform a number of fatality checks, then die gracefully if necessary
00116         $this->DBname = $db;
00117         if (!$this->interface = databaseInterfaceFactory::getInterface()) {
00118             if ($return_on_error) {
00119                 $this->_errorNum = _ALIRO_DB_NO_INTERFACE;
00120                 return;
00121             }
00122             $this->forceOffline(_ALIRO_DB_NO_INTERFACE);
00123         }
00124         if (!($this->_resource = $this->interface->connect($host, $user, $pass, $db))) {
00125             $this->_errorMsg = $this->interface->connectError();
00126             if ($return_on_error) {
00127                 $this->_errorNum = _ALIRO_DB_CONNECT_FAILED;
00128                 return;
00129             }
00130             $this->forceOffline(_ALIRO_DB_CONNECT_FAILED);
00131         }
00132         $this->interface->setCharset('utf8');
00133         $this->cache = new aliroSimpleCache('aliroAbstractDatabase', true);
00134         $this->DBInfo = $this->cache->get($host.$db.$user.$table_prefix, _ALIRO_DATABASE_CACHE_TIME);
00135         if (!$this->DBInfo) {
00136             $this->DBinfo = new stdClass();
00137             $this->DBInfo->DBTables = array();
00138             $this->DBInfo->DBFields = array();
00139             $this->DBInfo->DBFieldsByName = array();
00140         }
00141         $this->_table_prefix = $table_prefix;
00142         $this->getTableInfo();
00143     }
00144 
00145     public function __destruct () {
00146         try {
00147             @session_write_close();
00148             if (aliro::getInstance()->installed) $this->saveStats();
00149         } catch (databaseException $exception) {
00150             exit('DB Error during shutdown');
00151         }
00152     }
00153 
00154     private function clearCache () {
00155         $this->cache->clean();
00156     }
00157     
00158     private function getTableInfo () {
00159         if (count($this->DBInfo->DBTables) == 0) {
00160             $this->setBareQuery ("SHOW TABLES");
00161             if ($results = $this->loadResultArray()) foreach ($results as $result) $this->DBInfo->DBTables[] = $this->restoreOnePrefix($result);
00162             $this->cache->save($this->DBInfo);
00163         }
00164     }
00165 
00166     private function storeFields ($tablename) {
00167         if (!isset($this->DBInfo->DBFields[$tablename])) {
00168             $this->DBInfo->DBFields[$tablename] = $this->doSQLget("SHOW FIELDS FROM `$tablename`");
00169             $this->DBInfo->DBFieldsByName[$tablename] = array();
00170             foreach ($this->DBInfo->DBFields[$tablename] as $field) $this->DBInfo->DBFieldsByName[$tablename][$field->Field] = $field;
00171             $this->cache->save($this->DBInfo);
00172         }
00173     }
00174     
00175     public function getName () {
00176         return $this->DBname;
00177     }
00178 
00179     public function getAllFieldInfo ($tablename) {
00180         $this->storeFields($tablename);
00181         return $this->DBInfo->DBFields[$tablename];
00182     }
00183 
00184     public function getAllFieldNames ($tablename) {
00185         $this->storeFields($tablename);
00186         return array_keys($this->DBInfo->DBFieldsByName[$tablename]);
00187     }
00188 
00189     public function addFieldIfMissing ($tablename, $fieldname, $fieldspec, $alterIfPresent=false) {
00190         if (in_array($fieldname, $this->getAllFieldNames($tablename))) {
00191             if ($alterIfPresent) return $this->alterField($tablename, $fieldname, $fieldspec);
00192             return false;
00193         }
00194         $this->doSQL("ALTER TABLE $tablename ADD `$fieldname` ".$fieldspec);
00195         $this->clearCache();
00196         return true;
00197     }
00198 
00199     public function alterField ($tablename, $fieldname, $fieldspec) {
00200         if (in_array($fieldname, $this->getAllFieldNames($tablename))) return false;
00201         $this->doSQL("ALTER TABLE $tablename CHANGE COLUMN `$fieldname` ".$fieldspec);
00202         $this->clearCache();
00203         return true;
00204     }
00205 
00206     public function getFieldInfo ($tablename, $fieldname) {
00207         $this->storeFields($tablename);
00208         return isset($this->DBInfo->DBFieldsByName[$tablename][$fieldname]) ? $this->DBInfo->DBFieldsByName[$tablename][$fieldname] : null;
00209     }
00210 
00211     public function setFieldValue ($value) {
00212         if (is_numeric($value)) {
00213             if ((string) $value == (string) (int) $value) return (string) $value;
00214             else return "'".(string) $value."'";
00215         }
00216         $value = $this->getEscaped($value);
00217         return "'".$value."'";
00218     }
00219 
00220     // Expects parameter to be of the form #__name_of_table, so no need to look for DB prefix
00221     public function tableExists ($tablename) {
00222         return in_array($tablename, $this->DBInfo->DBTables);
00223     }
00224 
00225     protected function forceOffline ($error_number) {
00226             new aliroOffline ($error_number);
00227             // Uncomment this for more diagnostics
00228             // echo aliroRequest::trace();
00229             exit();
00230     }
00231 
00232     // Deprecated in favour of leaving all error handling to the system
00233     public function getErrorNum() {
00234         return $this->_errorNum;
00235     }
00236 
00237     // Deprecated as above
00238     public function getErrorMsg() {
00239         return str_replace( array( "\n", "'" ), array( '\n', "'" ), $this->_errorMsg );
00240     }
00241 
00242     // Takes a string and escapes any characters needing it
00243     public function getEscaped($text) {
00244         return $this->interface->getEscaped($text);
00245     }
00246 
00247     // Deprecated - does not add enough value
00248     public function Quote( $text ) {
00249         return '\''.$this->getEscaped($text).'\'';
00250     }
00251 
00252     // No conversion of prefix marker - use only internally
00253     protected function setBareQuery($sql) {
00254         $this->_sql = $sql;
00255     }
00256 
00257     // Replaces #_ by the chosen database prefix and saves the query
00258     public function setQuery( $sql, $cached=false, $prefix='#__' ) {
00259         $this->_sql = $this->replacePrefix($sql, $prefix);
00260         $this->_cached = $cached;
00261     }
00262 
00263     // Carries out prefix marker replacement
00264     public function replacePrefix ($sql, $prefix='#__') {
00265         $text = $sql;
00266         $result = '';
00267         while ($text) {
00268             $firstquote = $this->nonzeromin(strpos($text, "'"), strpos($text, '"'));
00269             if ($firstquote) {
00270                 $result .= str_replace($prefix, $this->_table_prefix, substr($text,0,$firstquote));
00271                 $text = substr($text, $firstquote);
00272                 $endquote = $this->findMatchingQuote($text, $text[0]);
00273                 $result .= substr($text, 0, $endquote+1);
00274                 $text = substr($text, $endquote+1);
00275             }
00276             else {
00277                 $result .= str_replace($prefix, $this->_table_prefix, $text);
00278                 break;
00279             }
00280         }
00281         return $result;
00282     }
00283 
00284     private function nonzeromin ($x, $y) {
00285         if (false === $x) return $y;
00286         if (false === $y) return $x;
00287         return min($x, $y);
00288     }
00289 
00290     private function findMatchingQuote ($text, $quote) {
00291         $skip = 1;
00292         do {
00293             $endquote = $quote ? strpos($text, $quote, $skip) : strlen($text) - 1;
00294             if ($endquote) $skip = $endquote+1;
00295         }
00296         while ($endquote AND '\\' == $text[$endquote-1]);
00297         if ($endquote) return $endquote;
00298         else return strlen($text)-1;
00299     }
00300 
00301     public function restoreOnePrefix ($tablename) {
00302         if (substr($tablename, 0, strlen($this->_table_prefix)) === $this->_table_prefix) return '#__'.substr($tablename, strlen($this->_table_prefix));
00303         else return $tablename;
00304     }
00305 
00306     // Returns stored SQL with replacements, ready to display
00307     public function getQuery ($sql='') {
00308         if ($sql == '') $sql = $this->_sql;
00309         return "<pre>" . htmlspecialchars( $sql ) . "</pre>";
00310     }
00311 
00312     public function query ($sql='') {
00313         if (empty($sql)) $sql = $this->_sql;
00314         $timer = new aliroProfiler('Database timer');
00315         if ($this->_cursor = $this->interface->query($sql)) {
00316             $this->_errorNum = 0;
00317             $this->_errorMsg = '';
00318             $stats = new stdClass;
00319             $stats->timer = $timer->getElapsed();
00320             $stats->trace = aliroRequest::trace(false);
00321             $stats->sql = $sql;
00322             self::$stats[] = $stats;
00323             $this->_log[] = htmlspecialchars($sql).'<br />'.$timer->mark('secs for query').'<br />'.$stats->trace;
00324             return $this->_cursor;
00325         }
00326         else {
00327             $this->_errorNum = $this->interface->errno();
00328             $this->_errorMsg = $this->interface->error()." SQL=$sql";
00329             throw new databaseException ($this->DBname, $this->_errorMsg, $this->_sql, $this->_errorNum, aliroRequest::trace());
00330         }
00331     }
00332 
00333     // Combined operation - takes SQL and executes it
00334     public function doSQL ($sql) {
00335         $this->setQuery($sql);
00336         return $this->query();
00337     }
00338 
00339     // Combined operation - as above - and returns an array of objects of the specified class
00340     public function doSQLget ($sql, $classname='stdClass', $key='', $max=0) {
00341         $this->setQuery($sql);
00342         $rows = $this->retrieveResults ($key, 0, 'object');
00343         if ('stdClass' == $classname) return $max ? array_slice($rows, 0, $max) : $rows;
00344         $result = array();
00345         foreach ($rows as $sub=>$row) {
00346             $next = new $classname();
00347             foreach (get_object_vars($row) as $field=>$value) $next->$field = $value;
00348             $result[$sub] = $next;
00349             if ($max AND count($result) >= $max) return $result;
00350         }
00351         return $result;
00352     }
00353 
00354     public function query_batch() {
00355         $this->_errorNum = 0;
00356         $this->_errorMsg = '';
00357         if ($this->interface->multiQuery($this->_sql)) {
00358             do $result = $this->interface->storeResult();
00359             while ($this->interface->nextResult());
00360         }
00361     }
00362 
00363     public function getNumRows ($cur=null) {
00364         return $this->interface->getNumRows($cur);
00365     }
00366 
00367     public function getAffectedRows () {
00368         return $this->interface->getAffectedRows();
00369     }
00370 
00371     protected function retrieveResults ($key='', $max=0, $result_type='row') {
00372         $results = array();
00373         if (!in_array($result_type, array ('row', 'object', 'assoc'))) die ('unexpected result type='.$result_type);
00374         $sql_function = $this->interface->getFetchFunc().$result_type;
00375         if ($cur = $this->query()) {
00376             while ($row = $sql_function($cur)) {
00377                 if ($key != '') $results[(is_array($row) ? $row[$key] : $row->$key)] = $row;
00378                 else $results[] = $row;
00379                 if ($max AND count($results) >= $max) break;
00380             }
00381             $this->interface->freeResultSet($cur);
00382         }
00383         return $results;
00384     }
00385 
00386     public function loadResult() {
00387         $results = $this->retrieveResults('', 1, 'row');
00388         if (count($results)) return $results[0][0];
00389         else return null;
00390     }
00391 
00392     public function loadResultArray($numinarray = 0) {
00393         $results = $this->retrieveResults('', 0, 'row');
00394         foreach ($results as $result) $values[] = $result[$numinarray];
00395         return isset($values) ? $values : null;
00396     }
00397 
00398     public function loadAssocList( $key='' ) {
00399         $results = $this->retrieveResults($key, 0, 'assoc');
00400         if (count($results)) return $results;
00401         else return null;
00402     }
00403 
00404     // Of questionable value - not used in Aliro except for compatibility in mambofunc
00405     public function mosBindArrayToObject( $array, $obj, $ignore='', $prefix=NULL, $checkSlashes=true ) {
00406         if (!is_array($array) OR !is_object($obj)) return false;
00407         if ($prefix == null) $prefix = '';
00408         foreach (get_object_vars($obj) as $k => $v) {
00409             if( substr( $k, 0, 1 ) != '_' AND strpos($ignore, $k) === false) {
00410                 if (isset($array[$prefix.$k])) {
00411                     $obj->$k = ($checkSlashes AND get_magic_quotes_gpc()) ? $this->mosStripslashes( $array[$prefix.$k] ) : $array[$prefix.$k];
00412                 }
00413             }
00414         }
00415         return true;
00416     }
00417 
00418     // Of questionable value - not used in Aliro except for compatibility in mambofunc
00419     public function mosStripslashes($value) {
00420         if (is_string($value)) $ret = stripslashes($value);
00421         elseif (is_array($value)) {
00422             $ret = array();
00423             foreach ($value as $key=>$val) $ret[$key] = $this->mosStripslashes($val);
00424         }
00425         else $ret = $value;
00426         return $ret;
00427     } // mosStripSlashes
00428 
00429     // May be obscure to users how this will behave depending on prior setting of parameter
00430     public function loadObject(&$object) {
00431         if (!is_object($object)) $results = $this->retrieveResults('', 1, 'object');
00432         else $results = $this->retrieveResults('', 1, 'assoc');
00433         if (0 == count($results)) return false;
00434         if (!is_object($object)) $object = $results[0];
00435         else {
00436             if (is_subclass_of($object, 'aliroDBGeneralRow')) $object->bind($results[0], '', false);
00437             else foreach (get_object_vars($object) as $k => $v) {
00438                 if ($k[0] != '_' AND isset($results[0][$k])) $object->$k = $results[0][$k];
00439             }
00440         }
00441         return true;
00442     }
00443 
00444     public function loadObjectList( $key='' ) {
00445         $results = $this->retrieveResults($key, 0, 'object');
00446         if (count($results)) return $results;
00447         else return null;
00448     }
00449 
00450     public function loadRow() {
00451         $results = $this->retrieveResults('', 1, 'row');
00452         if (count($results)) return $results[0];
00453         else return null;
00454     }
00455 
00456     public function loadRowList( $key='' ) {
00457         $results = $this->retrieveResults($key, 0, 'row');
00458         if (count($results)) return $results;
00459         else return null;
00460     }
00461 
00462     public function insertObject ($table, $object, $keyName=NULL) {
00463         $dbfields = $this->getAllFieldNames($table);
00464         foreach ($dbfields as $name) {
00465             if (!isset($object->$name) OR is_array($object->$name) OR is_object($object->$name)) continue;
00466             $fields[] = "`$name`";
00467             $values[] = $this->setFieldValue($object->$name);
00468         }
00469         if (isset($fields)) {
00470             $result = $this->doInsertion ($table, implode( ",", $fields ), implode( ",", $values ));
00471             // insertid() is only meaningful if non-zero
00472             $autoinc = $this->insertid();
00473             if ($autoinc AND $keyName AND !is_array($keyName)) $object->$keyName = $autoinc;
00474             return $result;
00475         }
00476         else {
00477             trigger_error (sprintf(T_('Insert into table %s but no fields'), $this->tableName));
00478             echo aliroRequest::trace();
00479             return false;
00480         }
00481     }
00482 
00483     private function doInsertion ($table, $fields, $values) {
00484         return $this->doSQL("INSERT INTO $table ($fields) VALUES ($values)");
00485     }
00486 
00487     public function updateObject ($table, $object, $keyName, $updateNulls=true) {
00488         $dbfields = $this->getAllFieldNames($table);
00489         foreach ($dbfields as $name) {
00490             if (!isset($object->$name) OR is_array($object->$name) OR is_object($object->$name)) {
00491                 if ($updateNulls) $value = "''";
00492                 else continue;
00493             }
00494             else $value = $this->setFieldValue($object->$name);
00495             $setter = "`$name` = $value";
00496             if (is_array($keyName) AND in_array($name, $keyName)) $where[] = $setter;
00497             elseif ($name == $keyName) $where[] = $setter;
00498             else $setters[] = $setter;
00499         }
00500         if (!isset($where)) {
00501             trigger_error (sprintf(T_('Update table %s but no key fields'), $table));
00502             return false;
00503         }
00504         if (isset($setters)) return $this->doUpdate ($table, implode (', ', $setters), implode (' AND ' , $where));
00505         return true;
00506     }
00507 
00508     private function doUpdate ($table, $setters, $conditions) {
00509         return $this->doSQL("UPDATE $table SET $setters WHERE $conditions");
00510     }
00511 
00512     // Deprecated in favour of allowing the system to handle errors
00513     public function stderr( $showSQL = false ) {
00514         return "DB function failed with error number $this->_errorNum"
00515         ."<br /><font color=\"red\">$this->_errorMsg</font>"
00516         .($showSQL ? "<br />SQL = <pre>$this->_sql</pre>" : '');
00517     }
00518 
00519     public function insertid() {
00520         return $this->interface->insertid();
00521     }
00522 
00523     public function getVersion()
00524     {
00525         return $this->interface->getVersion();
00526     }
00527 
00531     public function GenID () {
00532         return '0';
00533     }
00534 
00535     // Usual use is to check for existence of a table - easier to use tableExists which expects #_ type table name
00536     // Also more efficient as tableExists uses cache
00537     public function getTableList() {
00538         $this->setQuery('SHOW tables');
00539         return $this->loadResultArray();
00540     }
00541 
00542     // This is probably useful - what exactly does it do?
00543     public function getTableCreate( $tables ) {
00544         $result = array();
00545 
00546         foreach ($tables as $tblval) {
00547             $this->setQuery( 'SHOW CREATE table ' . $tblval );
00548             $this->query();
00549             $result[$tblval] = $this->loadResultArray( 1 );
00550         }
00551 
00552         return $result;
00553     }
00554 
00555     // This is also potentially useful, but requires translated prefix.
00556     // Easier to use getAllFieldNames repeatedly - also more efficient, as uses cache
00557     public function getTableFields( $tables ) {
00558         $result = array();
00559 
00560         foreach ($tables as $tblval) {
00561             $fields = $this->doSQLget ( 'SHOW FIELDS FROM ' . $tblval );
00562             foreach ($fields as $field) {
00563                 $result[$tblval][$field->Field] = preg_replace("/[(0-9)]/",'', $field->Type );
00564             }
00565         }
00566 
00567         return $result;
00568     }
00569     
00570     public function getCount () {
00571         return count($this->_log);
00572     }
00573 
00574     public function getLogged () {
00575         $text = '<h4>'.$this->getCount().' queries executed</h4>';
00576         foreach ($this->_log as $k=>$sql) $text .= "\n".($k+1)."<br />".$sql.'<hr />';
00577         if (count($this->_log)) return $text;
00578         else return '';
00579     }
00580 
00581     private function saveStats () {
00582         new aliroObjectSorter(self::$stats, 'timer');
00583         $n = count(self::$stats);
00584         if ($n > 0) {
00585             $median = self::$stats[intval($n/2)]->timer;
00586             $total = 0.0;
00587             foreach (self::$stats as $stat) $total += $stat->timer;
00588             $mean = $total/$n;
00589             $var = 0.0;
00590             foreach (self::$stats as $stat) $var += ($stat->timer - $mean) * ($stat->timer - $mean);
00591             $stdev = sqrt($var);
00592             $best = self::$stats[0]->timer;
00593             $worst = self::$stats[$n-1]->timer;
00594             $elapsed = aliro::getInstance()->getElapsed();
00595             $memory = memory_get_usage();
00596             $uri = htmlspecialchars($_SERVER['REQUEST_URI'], ENT_QUOTES, 'UTF-8');
00597             aliroCoreDatabase::getInstance()->doSQL("INSERT INTO #__query_stats (count, mean, median, stdev, best, worst, total, elapsed, memory, uri) VALUES ($n, '$mean', '$median', '$stdev', '$best', '$worst', '$total', '$elapsed', '$memory', '$uri')");
00598             $queryid = $this->insertid();
00599             $stats = self::$stats;
00600             foreach ($stats as $stat) {
00601                 if (0.50 < $stat->timer) {
00602                     $querytext = htmlspecialchars($stat->sql, ENT_QUOTES);
00603                     $tracetext = $this->getEscaped($stat->trace, ENT_QUOTES);
00604                     $sql = "INSERT INTO {$this->_table_prefix}query_slow (queryid, time, trace, querytext) VALUES ($queryid, '$stat->timer', '$tracetext', '$querytext')";
00605                     $this->interface->query($sql);
00606                 }
00607             }
00608         }
00609         self::$stats = array();
00610     }
00611 
00612 }
00613 
00614 class database extends aliroAbstractDatabase {
00615 
00616 }
00617 
00618 class aliroDatabaseHandler extends aliroAbstractDatabase {
00619 
00620 }
00621 
00622 class aliroDatabase {
00623 
00624     protected static $instance = __CLASS__;
00625     protected $database;
00626 
00627     protected function __construct () {
00628         $credentials = aliroCore::getConfigData('credentials.php');
00629         $this->database = new aliroDatabaseHandler ($credentials['dbhost'], $credentials['dbusername'], $credentials['dbpassword'], $credentials['dbname'], $credentials['dbprefix']);
00630     }
00631 
00632     protected function __clone () {
00633         // Enforce singleton
00634     }
00635 
00636     public function __call ($method, $args) {
00637         return call_user_func_array(array($this->database, $method), $args);
00638     }
00639     
00640     // Required because parameter must be passed by reference, not by value
00641     public function loadObject (&$object) {
00642         return $this->database->loadObject($object);
00643     }
00644 
00645     public static function getInstance () {
00646         return is_object(self::$instance) ? self::$instance : (self::$instance = new self::$instance);
00647     }
00648 
00649 }
00650 
00651 class mamboDatabase extends aliroDatabase {
00652     // Just an alias really
00653 }
00654 
00655 // Similar to aliroDatabase but with any conflicting methods overriden
00656 class joomlaDatabase extends aliroDatabase {
00657     protected static $instance = __CLASS__;
00658     
00659     public static function getInstance () {
00660         return is_object(self::$instance) ? self::$instance : (self::$instance = new self::$instance);
00661     }
00662     
00663     public function loadObject () {
00664         $object = null;
00665         $this->database->loadObject($object);
00666         return $object;
00667     }
00668 }
00669 
00670 class aliroCoreDatabase extends aliroDatabase {
00671 
00672     protected static $instance = __CLASS__;
00673 
00674     protected function __construct () {
00675         $credentials = aliroCore::getConfigData('corecredentials.php');
00676         $this->database = new aliroDatabaseHandler ($credentials['dbhost'], $credentials['dbusername'], $credentials['dbpassword'], $credentials['dbname'], $credentials['dbprefix']);
00677     }
00678 
00679     public static function getInstance () {
00680         return is_object(self::$instance) ? self::$instance : (self::$instance = new self::$instance);
00681     }
00682 }

Generated on Wed May 14 13:01:55 2008 for ALIRO by  doxygen 1.5.5