<?php



class xxx_DBO extends PDO {



// Converts database table column name style into object property naming style,

// given a PDO recordset.

public function convertRows (& $rsRows ) {

$asRows = array();

foreach ( $rsRows as $rwRow ) {

$asRow = array();

foreach ( $rwRow as $sOldKey => $vVal ) {

if ( intval ( $sOldKey ) === $sOldKey ) {

continue;

}

$sNewKey = self :: _getObjectKeyName ( $sOldKey );

$asRow [ $sNewKey ] = $vVal ;

}

array_push ( $asRows , $asRow );

$asRow = '' ;

}

return $asRows ;

}



// Converts a "(object) array()" record object into a PDO Statement object,

// in this case for UPDATE statements. Also translates object property naming

// into typical db field naming.

public function createUpdate ( $oRec ) {

if (isset( $oRec -> Table )) {

$sTable = $oRec -> Table ;

}

if (isset( $oRec -> Where )) {

$sWhere = $oRec -> Where ;

}

unset( $oRec -> Table );

unset( $oRec -> Where );

if ((empty( $sTable )) or (empty( $sWhere ))) {

die( '<strong>Missing either Table or Where properties on createUpdate.</strong>' );

}

$s = '' ;

foreach ( $oRec as $sKey => $sVal ) {

$sKey = self :: _getDBKeyName ( $sKey );

$s .= $sKey . '=:' . $sKey . ',' ;

}

$s = substr ( $s , 0 , - 1 );

$sTable = str_replace ( '--' , '' , $sTable );

$sTable = str_replace ( ';' , '' , $sTable );

$sWhere = str_replace ( '--' , '' , $sWhere );

$sSQL = "

UPDATE

$sTable

SET

$s

WHERE

$sWhere ;

" ;

$PDO = xxx_PDO :: getDB ();

$st = $PDO -> prepare ( $sSQL );

foreach ( $oRec as $sKey => $sVal ) {

$sKey = self :: _getDBKeyName ( $sKey );

$st -> bindValue ( ':' . $sKey , $sVal );

}

return $st ;

}



// Converts a "(object) array()" record object into a PDO Statement object,

// in this case for INSERT statements. Also translates object property naming

// into typical db field naming.

public function createInsert ( $oRec ) {

$sTable = $oRec -> Table ;

unset( $oRec -> Table );

if (empty( $sTable )) {

die( '<strong>Missing Table properties on createInsert.</strong>' );

}

$s1 = '' ; $s2 = '' ;

foreach ( $oRec as $sKey => $sVal ) {

$sKey = self :: _getDBKeyName ( $sKey );

$s1 .= '' . $sKey . ',' ;

$s2 .= ':' . $sKey . ',' ;

}

$s1 = substr ( $s1 , 0 , - 1 );

$s2 = substr ( $s2 , 0 , - 1 );

$sTable = str_replace ( '--' , '' , $sTable );

$sTable = str_replace ( ';' , '' , $sTable );

$sSQL = "

INSERT INTO $sTable (

$s1

) VALUES (

$s2

);

" ;

$PDO = xxx_PDO :: getDB ();

$st = $PDO -> prepare ( $sSQL );

foreach ( $oRec as $sKey => $sVal ) {

$sKey = self :: _getDBKeyName ( $sKey );

$st -> bindValue ( ':' . $sKey , $sVal );

}

return $st ;

}



// Converts my typical database table field naming style with an object property naming style.

private static function _getObjectKeyName (& $sKey ) {

$sKey = strtolower ( $sKey );

$sKey = str_replace ( 'fkey_' , 'fk_' , $sKey );

$sKey = str_replace ( 'dt_' , 'Date_' , $sKey );

$sKey = str_replace ( '_' , ' ' , $sKey );

$sKey = ucwords ( $sKey );

$sKey = str_replace ( 'Ip ' , 'IP ' , $sKey );

$sKey = str_replace ( ' Ip' , ' IP' , $sKey );

$sKey = str_replace ( 'Url ' , 'URL ' , $sKey );

$sKey = str_replace ( ' Url' , ' URL' , $sKey );

$sKey = str_replace ( 'name' , 'Name' , $sKey ); //not a bug -- I conjoin name usually

$sKey = str_replace ( ' Id' , ' ID' , $sKey );

$sKey = str_replace ( 'Id ' , 'ID ' , $sKey );

$sKey = str_replace ( ' ' , '' , $sKey );

$sKey = ( $sKey == 'Id' ) ? 'ID' : $sKey ;

$sKey = ( $sKey == 'Ip' ) ? 'IP' : $sKey ;

$sKey = ( $sKey == 'Url' ) ? 'URL' : $sKey ;

$sKey = str_replace ( 'Fk' , 'FK' , $sKey );

$sKey = ( $sKey == 'UserName' ) ? 'Username' : $sKey ;

return $sKey ;

}



// Converts my typical object property naming style with a database table field naming style.

private static function _getDBKeyName (& $sKey ) {

foreach ( range ( 'A' , 'Z' ) as $c ) {

$sKey = str_replace ( $c , "_ $c " , $sKey );

}

$sKey = str_replace ( '_F_K_' , '_fkey_' , $sKey );

$sKey = str_replace ( '_I_D_' , '_id_' , $sKey );

$sKey = str_replace ( '_I_D' , '_id' , $sKey );

$sKey = str_replace ( '_I_P_' , '_ip_' , $sKey );

$sKey = str_replace ( '_I_P' , '_ip' , $sKey );

$sKey = str_replace ( '_U_R_L_' , '_url_' , $sKey );

$sKey = str_replace ( '_U_R_L' , '_url' , $sKey );

$sKey = str_replace ( '_Name' , 'name' , $sKey ); //not a bug -- I separate name usually

$sKey = str_replace ( '_Date_' , '_dt_' , $sKey );

$sKey = str_replace ( '_Date' , '_Date' , $sKey );

if ( strpos ( $sKey , '_' ) == 0 ) {

$sKey = substr ( $sKey , 1 );

}

$sLast = substr ( $sKey , - 1 );

if ( $sLast == '_' ) {

$sKey = strrev ( $sKey );

if ( strpos ( $sKey , '_' ) == 0 ) {

$sKey = substr ( $sKey , 1 );

}

$sKey = strrev ( $sKey );

}

$sKey = strtolower ( $sKey );

return $sKey ;

}



}





class xxx_PDO {



private static $_hInstance ;

private $_hDB ;



private static function _get_ANSI_SQLSTATE_Code (& $e ) {

$s = $e -> __toString ();

$asItems = explode ( '[' , $s );

$s = $asItems [ 1 ];

$asItems = explode ( ']' , $s );

$s = $asItems [ 0 ];

return trim ( $s );

}



public static function initDB () { // call this by bootstrap



$oDB = self :: _getInstance ();

try {

$oConn = new xxx_DBO ( xxx_Settings :: get ( 'DSN' ), xxx_Settings :: get ( 'DSN_USER' ), xxx_Settings :: get ( 'DSN_PASS' ));

} catch ( PDOException $e ) {

$SQLSTATE = self :: _get_ANSI_SQLSTATE_Code ( $e );

switch ( $SQLSTATE ) {

case 28000 :

$sErr = 'The database user is not created or the password is wrong for database user: ' . xxx_Settings :: get ( 'DSN_USER' );

break;

default:

echo 'SQL ERROR: ' ;

print_r ( $e -> getCode ());

die();

}

die( '<strong>' . $sErr . '</strong>' );

}

$sTest = xxx_Settings :: get ( 'DSN' );

if ( strpos ( ' ' . $sTest , 'mysql:' )> 0 ) {

$oConn -> setAttribute ( PDO :: MYSQL_ATTR_MAX_BUFFER_SIZE , 1024 * 1024 * 50 );

}

unset( $sTest );

$oConn -> setAttribute ( PDO :: ATTR_ERRMODE , PDO :: ERRMODE_EXCEPTION );

$oConn -> setAttribute ( PDO :: ATTR_PERSISTENT , TRUE );

$oConn -> setAttribute ( PDO :: ATTR_CURSOR , PDO :: CURSOR_FWDONLY );



$oDB -> _hDB = $oConn ;

}



public static function getDB () { // call this to get last established database connection handle

$oDB = self :: _getInstance ();

return $oDB -> _hDB ;

}



private static function _getInstance () {

if ( self :: $_hInstance == null ) {

$sClassName = __CLASS__ ;

self :: $_hInstance = new $sClassName ();

}

return self :: $_hInstance ;

}



} //end xxx_PDO