Source for file database.php
Documentation is available at database.php
* @copyright Refer to copyright.php
* @license http://www.gnu.org/copyleft/gpl.html GNU/GPL
* @author Mambo Foundation Inc see README.php
* Database connector class
/** @var string Internal variable to hold the query sql */
/** @var int Internal variable to hold the database error number */
/** @var string Internal variable to hold the database error message */
/** @var string Internal variable to hold the prefix used on all database tables */
/** @var Internal variable to hold the connector resource */
/** @var Internal variable to hold the last query cursor */
/** @var boolean Debug option */
/** @var array A log of queries */
/** @var string Null date */
* Database object constructor
* @param string Database host
* @param string Database user name
* @param string Database user password
* @param string Database name
* @param string Common prefix for all tables
function database( $host=
'localhost', $user, $pass, $db, $table_prefix ) {
global $configuration,$charset;
$mysql_charsets['utf-8']=
'utf-8';
$mysql_charsets['iso-8859-1']=
'latin1';
$mysql_charsets['iso-8859-15']=
'latin1';
$mysql_charsets['koi8-r']=
'koi8r';
$mysql_charsets['windows-1251']=
'cp1251';
$mysql_charsets['cp1251']=
'cp1251';
$mysql_charsets['gb2312']=
'gb2312';
$mysql_charsets['gb18030']=
'gb2312';
$mysql_charsets['gbk']=
'gb2312';
$mysql_charsets['big5-hkscs']=
'big5';
$mysql_charsets['big5']=
'big5';
$mysql_charsets['euc-tw']=
'gb2312';
$mysql_charsets['iso-8859-2']=
'latin2';
$mysql_charsets['windows-1250']=
'latin2';
$mysql_charsets['iso-8859-7']=
'latin7';
$mysql_charsets['iso-8859-8-i']=
'hebrew';
$mysql_charsets['iso-8859-8']=
'hebrew';
$mysql_charsets['sjis']=
'sjis';
$mysql_charsets['windows-1257']=
'latin7';
$mysql_charsets['iso-8859-13']=
'latin7';
$mysql_charsets['cp-866']=
'cp1251';
$mysql_charsets['iso-8859-5']=
'latin5';
$mysql_charsets['koi8-u']=
'koi8r';
$mysql_charsets['windows-1252']=
'latin1';
$mysql_charsets['tis-620']=
'tis620';
$mysql_charsets['iso-8859-9']=
'latin5';
$mysql_charsets['windows-1256']=
'cp1256';
$mysql_charsets['georgian-ps']=
'geostd8';
$mysql_charsets['euc-jp']=
'eucjpms';
$mysql_charsets['euc-kr']=
'euckr';
$mysql_charsets['iso-8859-6']=
'cp1256';
$mysql_charsets['windows-1258']=
'latin1'; //No better match
// perform a number of fatality checks, then die gracefully
if(floatval(mysql_get_client_info())>=
4.1){
$charset=isset
($charset)?
$charset:
'utf-8';
$charset = isset
($configuration)?
$configuration->current_language->charset:
$charset;
$cs=
$mysql_charsets[$charset];
mysql_query( "SET CHARSET '" .
$cs.
"'" );
$mosSystemError =
$error_number;
include $basePath .
'/../configuration.php';
include $basePath .
'/../offline.php';
function debug( $level ) {
//echo "<pre>" . $this->_sql . "</pre>\n";
echo
'<br />'.
$back['file'].
':'.
$back['line'];
* @return int The error number for the most recent query
* @return string The error message for the most recent query
* Get a database escaped string
return mysql_escape_string( $text );
return mysql_real_escape_string( $text );
* Get a quoted database escaped string
function Quote( $text ) {
return '\'' .
mysql_escape_string( $text ) .
'\'';
return '\'' .
mysql_real_escape_string( $text ) .
'\'';
* Sets the SQL query string for later execution.
* @param string The SQL query
* Sets the SQL query string for later execution.
* This function replaces a string identifier <var>$prefix</var> with the
* string held is the <var>_table_prefix</var> class variable.
* @param string The SQL query
* @param string The common table prefix
function setQuery( $sql, $prefix=
'#__' ) {
// This is maintenance code for catching particular SQL statements
// if (strpos($this->_sql,'SELECT menutype') === 0) debug_print_backtrace();
* This function replaces a string identifier <var>$prefix</var> with the
* string held is the <var>_table_prefix</var> class variable.
* @param string The SQL query
* @param string The common table prefix
* @author thede, David McKinnis
$single =
preg_match("/\'([^\\\']|\\.)*'/", $sql,$matches_single,PREG_OFFSET_CAPTURE);
if ($double =
preg_match('/\"([^\\\"]|\\.)*"/', $sql,$matches_double,PREG_OFFSET_CAPTURE) OR $single) {
if ($single ==
0 OR ($double AND $matches_double[0][1] <
$matches_single[0][1])) {
$sql =
substr($sql,$matches_double[0][1]+
strlen($matches_double[0][0]));
$sql =
substr($sql,$matches_single[0][1]+
strlen($matches_single[0][0]));
* @return string The current value of the internal SQL vairable
if ($sql ==
'') $sql =
$this->_sql;
* @return mixed A database resource if successful, FALSE if not.
function query($sql =
'') {
if ($sql ==
'') $sql =
$this->_sql;
function query_batch( $abort_on_error=
true, $p_transaction_safe =
false) {
if ($p_transaction_safe) {
$si =
mysql_get_server_info();
if ($m[1] >=
4) $prefix =
'START TRANSACTION; ';
if ($m[3] >=
19) $prefix =
'BEGIN WORK; ';
elseif ($m[3] >=
17) $prefix =
'BEGIN; ';
if ($prefix) $this->_sql =
$prefix.
$this->_sql.
'; COMMIT;';
foreach ($query_split as $command_line) {
$command_line =
trim( $command_line );
if ($command_line !=
'') {
if (!$this->query($command_line)) {
return $error ?
false :
true;
if (!($cur =
$this->query("EXPLAIN ".
$this->_sql))) return null;
$headline =
$header =
$body =
'';
$buf =
'<table cellspacing="1" cellpadding="2" border="0" bgcolor="#000000" align="center">';
while ($row =
mysql_fetch_assoc($cur)) {
foreach ($row as $k=>
$v) {
if ($headline ==
'') $header .=
"<th bgcolor=\"#ffffff\">$k</th>";
$body .=
"<td bgcolor=\"#ffffff\">$v</td>";
$buf .=
"<tr>$headline</tr>$body</table><br /> ";
mysql_free_result( $cur );
return "<div style=\"background-color:#FFFFCC\" align=\"left\">$buf</div>";
* @return int The number of rows returned from the most recent query - SELECT only
return mysql_num_rows( $cur ?
$cur :
$this->_cursor );
* @return int The number of rows affected by the most recent query - INSERT, UPDATE, DELETE
return mysql_affected_rows( $this->_resource );
* Load an array of retrieved database objects or values
* @param int Database cursor
* @param string The field name of a primary key
* @return array If <var>key</var> is empty as sequential list of returned records.
* If <var>key</var> is not empty then the returned array is indexed by the value
* the database key. Returns <var>null</var> if the query fails.
$sql_function =
'mysql_fetch_'.
$result_type;
if ($cur =
$this->query()) {
while ($row =
$sql_function($cur)) {
$results[$row[$key]] =
$row;
$results[$row->$key] =
$row;
if ($max AND count($results) >=
$max) break;
* This method loads the first field of the first row returned by the query.
* @return The value returned in the query or null if the query failed.
if (count($results)) return $results[0][0];
* Load an array of single field results into an array
foreach ($results as $result) $values[] =
$result[$numinarray];
if (count($values)) return $values;
* Load a assoc list of database rows
* @param string The field name of a primary key
* @return array If <var>key</var> is empty as sequential list of returned records.
if (count($results)) return $results;
* Copy the named array content into the object as properties
* only existing properties of object are filled. when undefined in hash, properties wont be deleted
* @param array the input array
* @param obj byref the object to fill of any class
if ($prefix ==
null) $prefix =
'';
if( substr( $k, 0, 1 ) !=
'_' AND strpos($ignore, $k) ===
false) {
if (isset
($array[$prefix.
$k])) {
* Strip slashes from strings or arrays of strings
* @param value the input string or array
while (list
($key,$val) =
each($value)) {
* This global function loads the first row of a query into an object
* If an object is passed to this function, the returned row is bound to the existing elements of <var>object</var>.
* If <var>object</var> has a value of null, then all of the returned query fields returned in the object.
* @param string The SQL query
* @param object The address of variable
* Load a list of database objects
* @param string The field name of a primary key
* @return array If <var>key</var> is empty as sequential list of returned records.
* If <var>key</var> is not empty then the returned array is indexed by the value
* the database key. Returns <var>null</var> if the query fails.
if (count($results)) return $results;
* @return The first row of the query.
if (count($results)) return $results[0];
* Load a list of database rows (numeric column indexing)
* @param string The field name of a primary key
* @return array If <var>key</var> is empty as sequential list of returned records.
* If <var>key</var> is not empty then the returned array is indexed by the value
* the database key. Returns <var>null</var> if the query fails.
if (count($results)) return $results;
* Document::db_insertObject()
function insertObject( $table, &$object, $keyName =
NULL, $verbose=
false ) {
$fmtsql =
"INSERT INTO $table ( %s ) VALUES ( %s ) ";
if (!isset
($fields)) die ('class database method insertObject - no fields');
($verbose) && print
"$sql<br />\n";
if (!$this->query()) return false;
($verbose) && print
"id=[$id]<br />\n";
if ($keyName &&
$id) $object->$keyName =
$id;
* Document::db_updateObject()
* @param [type] $updateNulls
function updateObject( $table, &$object, $keyName, $updateNulls=
true ) {
$fmtsql =
"UPDATE $table SET %s WHERE %s";
if (is_array($v) OR is_object($v) OR $k[0] ==
'_' OR ($v ===
null AND !$updateNulls)) continue;
if( $k ==
$keyName ) { // PK not to be updated
$where =
"$keyName='" .
$this->getEscaped( $v ) .
"'";
if (!isset
($tmp)) return true;
if (!isset
($where)) die ('database class updateObject method - no key value');
* @param boolean If TRUE, displays the last SQL statement sent to the database
* @return string A standised error message
function stderr( $showSQL =
false ) {
return "DB function failed with error number $this->_errorNum"
.
"<br /><font color=\"red\">$this->_errorMsg</font>"
.
($showSQL ?
"<br />SQL = <pre>$this->_sql</pre>" :
'');
return mysql_insert_id();
return mysql_get_server_info();
* Fudge method for ADOdb compatibility
function GenID( $foo1=
null, $foo2=
null ) {
* @return array A list of all the tables in the database
* @param array A list of table names
* @return array A list the create SQL for the tables
foreach ($tables as $tblval) {
$this->setQuery( 'SHOW CREATE table ' .
$tblval );
* @param array A list of table names
* @return array An array of fields by table
foreach ($tables as $tblval) {
$this->setQuery( 'SHOW FIELDS FROM ' .
$tblval );
foreach ($fields as $field) {
$result[$tblval][$field->Field] =
preg_replace("/[(0-9)]/",'', $field->Type );
foreach ($this->_log as $k=>
$sql) {
echo
$k+
1 .
"\n" .
$sql .
'<hr />';
/* Helper method - maybe should go into database itself */
echo
"<script> alert('".
$this->getErrorMsg().
"'); window.history.go(-1); </script>\n";
/* Helper method - maybe could go into database itself */
foreach ($rows as $row) {
$next =
new $classname(0);
foreach ($target as $field=>
$value) {
if (isset
($row->$field)) $next->$field =
$row->$field;
parent::database($host, $user, $pw, $db, $prefix);
* mosDBAbstractRow Abstract Class.
* Parent classes to all database derived objects. Customisation will generally
* not involve tampering with this object.
* @author Martin Brampton counterpoint@mambo-foundation.org
/** @var string Name of the table in the db schema relating to child class */
/** @var string Name of the primary key field in the table */
/** @var string Error message */
* Object constructor to set table and key field
* Can be overloaded/supplemented by the child class
* @param string $table name of the table in the db schema relating to child class
* @param string $key name of the primary key field in the table
if ($table) $this->_tbl =
$table;
else $this->_tbl =
$this->tableName();
* can be overloaded/supplemented by the child class
* @return boolean True if the object is ok
* Checks if this object lacks the property given by the parameter
* @param string The name of the property
function lacks( $property ) {
$this->_error =
T_(sprintf('WARNING: %s does not support %s.', $thisclass, $property));
/* Move a database row object up or down through the ordering
/* @param int positive to move up, negative to move down
/* @param string Additional conditions on the WHERE clause to limit the effect
function move( $direction, $where=
'' ) {
$compops =
array (-
1 =>
'<', 0 =>
'=', 1 =>
'>');
$relation =
$compops[($direction>
0)-
($direction<
0)];
$ordering =
($relation ==
'<' ?
'DESC' :
'ASC');
$sql =
"SELECT $k, ordering FROM $this->_tbl WHERE ordering $relation $o1";
$sql .=
($where ?
"\n AND $where" :
'').
' ORDER BY ordering '.
$ordering.
' LIMIT 1';
$database->setQuery( $sql );
if ($database->loadObject($row)) {
$sql =
"UPDATE $this->_tbl SET ordering = (ordering=$o1)*$o2 + (ordering=$o2)*$o1 WHERE $k = $k1 OR $k = $k2";
* Compacts the ordering sequence of the selected records
* @param string Additional conditions on WHERE clause to limit ordering to a particular subset of records
function updateOrder( $where=
'', $cfid=
null, $order=
null ) {
if ($this->lacks('ordering')) return false;
if ($this->_tbl ==
"#__content_frontpage") $order2 =
", content_id DESC";
foreach ($cfid as $i=>
$id) {
$sql =
"UPDATE $this->_tbl SET ordering = ".
implode(' + ', $set).
' WHERE id IN ('.
implode(',', $cfid).
')';
$sql =
"SELECT $k, ordering FROM $this->_tbl "
.
($where ?
"\nWHERE $where" :
'')
.
"\nORDER BY ordering$order2";
$database->setQuery($sql);
if (!$rows =
$database->loadObjectList()) {
$this->_error =
$database->getErrorMsg();
foreach ($rows as $row) {
$sql =
"UPDATE $this->_tbl SET ordering=$i WHERE $k = ".
$row->$k;
* mosDBTable Abstract Class.
* Parent classes to all database derived objects. Customisation will generally
* not involve tampering with this object.
* @author Andrew Eddie <eddieajau@users.sourceforge.net
/** @var mosDatabase Database connector */
* @return bool True if DB query failed. Sets the error message
if ($this->_db->query()) return false;
* Filters public properties
* @param array List of fields to ignore
function filter( $ignoreList=
null ) {
$callcheck =
array('InputFilter', 'process');
if (!is_callable($callcheck)) require_once(mamboCore::get('mosConfig_absolute_path').
'/includes/phpInputFilter/class.inputfilter.php');
if (!in_array($k, $ignoreList)) $this->$k =
$iFilter->process($this->$k);
* @return string Returns the error message
* Gets the value of the class variable
* @param string The name of the class variable
* @return mixed The value of the class var (or null if no var of that name exists)
function get( $_property ) {
if(isset
( $this->$_property )) return $this->$_property;
* Returns an array of public properties
foreach (get_class_vars( get_class( $this ) ) as $key=>
$val) {
if (substr( $key, 0, 1 ) !=
'_') {
* Set the value of the class variable
* @param string The name of the class variable
* @param mixed The value to assign to the variable
function set( $_property, $_value ) {
$this->$_property =
$_value;
* binds a named array/hash to this object
* can be overloaded/supplemented by the child class
* @param array $hash named array
* @return null|string null is operation was satisfactory, otherwise returns an error
function bind( $array, $ignore=
"" ) {
if (is_array($array)) return $database->mosBindArrayToObject($array, $this, $ignore);
* binds an array/hash to this object
* @param int $oid optional argument, if not specifed then the value of current key is used
* @return any result from the database operation
function load( $oid=
null ) {
$this->$k =
$this->_db->getEscaped($oid);
if ($this->$k ===
null) return false;
$this->_db->setQuery("SELECT * FROM $this->_tbl WHERE $this->_tbl_key='".
$this->$k.
"'" );
return $this->_db->loadObject($this);
* Inserts a new row if id is zero or updates an existing row in the database table
* Can be overloaded/supplemented by the child class
* @param boolean If false, null object variables are not updated
* @return null|stringnull if successful otherwise returns and error message
function store( $updateNulls=
false ) {
if( $this->$k &&
!$migrate) $ret =
$this->_db->updateObject( $this->_tbl, $this, $this->_tbl_key, $updateNulls );
else $ret =
$this->_db->insertObject( $this->_tbl, $this, $this->_tbl_key );
* can be overloaded/supplemented by the child class
* @return true if successful otherwise returns and error message
function delete( $oid=
null ) {
if ($oid) $this->$k =
intval( $oid );
$this->_db->setQuery( "DELETE FROM $this->_tbl WHERE $this->_tbl_key = '".
$this->$k.
"'" );
if ($this->lacks('checked_out')) return false;
if ($oid !==
null) $this->$k =
$oid;
$time =
date( "Y-m-d H:i:s" );
// new way of storing editor, by id
$this->_db->setQuery( "UPDATE $this->_tbl"
.
"\nSET checked_out='$who', checked_out_time='$time'"
.
"\nWHERE $this->_tbl_key='".
$this->$k.
"'"
// old way of storing editor, by name
$this->_db->setQuery( "UPDATE $this->_tbl"
.
"\nSET checked_out='1', checked_out_time='$time', editor='".
$who.
"' "
.
"\nWHERE $this->_tbl_key='".
$this->$k.
"'"
return $this->_db->query();
if ($this->lacks('checked_out')) return false;
if ($oid !==
null) $this->$k =
$oid;
$this->_db->setQuery( "UPDATE $this->_tbl"
.
"\nSET checked_out='0', checked_out_time='0000-00-00 00:00:00'"
.
"\nWHERE $this->_tbl_key='".
$this->$k.
"'"
return $this->_db->query();
function hit( $oid=
null ) {
if ($oid !==
null) $this->$k =
intval( $oid );
$this->_db->setQuery( "UPDATE $this->_tbl SET hits=(hits+1) WHERE $this->_tbl_key='$key'" );
$this->_db->setQuery( "SELECT hits"
.
"\nFROM #__core_log_items"
.
"\nWHERE time_stamp='$now' AND item_table='$this->_tbl' AND item_id='$key'"
if ($hits) $this->_db->setQuery( "UPDATE #__core_log_items SET hits=(hits+1)"
.
"\nWHERE time_stamp='$now' AND item_table='$this->_tbl' AND item_id='".
$this->$k.
"'"
else $this->_db->setQuery( "INSERT INTO #__core_log_items VALUES"
.
"\n('$now','$this->_tbl','".
$this->$k.
"','1')"
* @param array Source array for binding to class vars
* @param string Filter for the order updating
* @returns TRUE if completely successful, FALSE if partially or not succesful.
function save( $source, $order_filter ) {
$filter_value =
$this->$order_filter;
$this->updateOrder( $order_filter ?
"`$order_filter`='$filter_value'" :
"" );
* Generic Publish/Unpublish function
* @param array An array of id numbers
* @param integer 0 if unpublishing, 1 if publishing
* @param integer The id of the user performnig the operation
$this->_error =
"No items selected.";
$this->_db->setQuery( "UPDATE $this->_tbl SET published='$publish'"
.
"\nWHERE $this->_tbl_key IN ($cids) AND (checked_out=0 OR checked_out='$myid')"
* Export item list to xml
* @param boolean Map foreign keys to text values
function toXML( $mapKeysToText=
false ) {
$xml =
'<record table="' .
$this->_tbl .
'"';
if ($mapKeysToText) $xml .=
' mapkeystotext="true"';
if ($k[0] ==
'_') continue; // internal field
$xml .=
'<' .
$k .
'><![CDATA[' .
$v .
']]></' .
$k .
'>';
* Abstract class for classes where the objects of the class can be relatively easily
* stored in a single database table. Can usually be adapted to more complex cases.
* Requires child classes to implement: tableName(), notSQL().
* tableName() must return the name of the database table, using #__ in the usual Mambo way
* notSQL() must return an array of strings, where each string is the name of a
* variable that is NOT in the database table, or is not written explicitly,
* e.g. the auto-increment key. If this is the ONLY non-SQL field, then the
* child class need not implement it, as that it is already in the abstract class.
* Child classes may implement timeStampField, in which case it must return the name
* of a field that will have a timestamp placed in it whenever the DB is written.
/* Stores all POST data where the name matches an object variable name */
if ($field!=
'id' AND $field[1] !=
'_' AND isset
($_POST[$field])) {
$this->$field =
trim($_POST[$field]);
/* Provided in case child class does not implement it. Can force any values */
/* within some limited range. In particular, can force bools to be 0 or 1 */
/* Updates an existing DB entry with the object's current values */
/* Deletes the current object from the DB */
$table =
$this->tableName();
$sql =
"DELETE FROM $table WHERE id=$this->id";
/* Provided in case the child class does not provide a method for timeStampField */
/* Provides SQL for updating the DB with the contents of the current object */
$tabname =
$this->tableName();
$sql =
"UPDATE $tabname SET %s WHERE id=$this->id";
if (!in_array($field,$exclude) AND $field[0] !=
'_') $setter[] =
$field.
"='".
$this->$field.
"'";
if ($timestamp) $setter[] =
$timestamp.
"='".
date('Y-m-d H:i:s').
"'";
/* Default method for identifying fields not to be written to the DB */
/* The child classes may override this and return more items in the array */
/* Provides SQL to insert the current object into the DB */
$tabname =
$this->tableName();
$sql =
"INSERT INTO $tabname (%s) VALUES (%s)";
if (!in_array($field,$exclude) AND $field[0] !=
'_') {
$values[] =
"'".
$this->$field.
"'";
$infields[] =
$timestamp;
$values[] =
"'".
date('Y-m-d H:i:s').
"'";
/* Copies any matching fields from some arbitrary object into the current object */
if ($field !=
'id' AND isset
($anObject->$field)) $this->$field =
$anObject->$field;
/* Ensures values can safely be written to DB; assumes magic quotes forced off */
if (!is_numeric($this->$field) AND is_string($this->$field)) $this->$field =
$database->getEscaped($this->$field);
/* Takes some arbitrary SELECT type SQL and places the first or only result into the current object */
$database->setQuery( $sql );
if (!$database->loadObject($this)) $this->id =
0;
Documentation generated on Mon, 05 May 2008 16:19:10 +0400 by phpDocumentor 1.4.0