oxdb.php

Go to the documentation of this file.
00001 <?php
00002 
00003 
00004 // Including main ADODB include
00005 require_once getShopBasePath() . 'core/adodblite/adodb.inc.php';
00006 
00010 class oxDb
00011 {
00016     const FETCH_MODE_NUM = ADODB_FETCH_NUM;
00017 
00022     const FETCH_MODE_ASSOC = ADODB_FETCH_ASSOC;
00023 
00028     public static $configSet = false;
00029 
00035     protected static $_instance = null;
00036 
00042     protected static $_oDB = null;
00043 
00049     protected static $_aTblDescCache = array();
00050 
00055     private static $_dbType = '';
00056 
00061     private static $_dbUser = '';
00062 
00067     private static $_dbPwd  = '';
00068 
00073     private static $_dbName = '';
00074 
00079     private static $_dbHost = '';
00080 
00085     private static $_iDebug = 0;
00086 
00091     private static $_blLogChangesInAdmin = false;
00092 
00097     private static $_iUtfMode = 0;
00098 
00103     private static $_sDefaultDatabaseConnection = null;
00104 
00109     private static $_aSlaveHosts;
00110 
00115     private static $_sAdminEmail;
00116 
00121     private static $_iMasterSlaveBalance;
00122 
00127     private static $_sLocalTimeFormat;
00128 
00133     private static $_sLocalDateFormat;
00134 
00142     public static function setConfig( $oConfig )
00143     {
00144         self::$_dbType                     = $oConfig->getVar( 'dbType' );
00145         self::$_dbUser                     = $oConfig->getVar( 'dbUser' );
00146         self::$_dbPwd                      = $oConfig->getVar( 'dbPwd' );
00147         self::$_dbName                     = $oConfig->getVar( 'dbName' );
00148         self::$_dbHost                     = $oConfig->getVar( 'dbHost' );
00149         self::$_iDebug                     = $oConfig->getVar( 'iDebug' );
00150         self::$_blLogChangesInAdmin        = $oConfig->getVar( 'blLogChangesInAdmin' );
00151         self::$_iUtfMode                   = $oConfig->getVar( 'iUtfMode' );
00152         self::$_sDefaultDatabaseConnection = $oConfig->getVar( 'sDefaultDatabaseConnection' );
00153         self::$_aSlaveHosts                = $oConfig->getVar( 'aSlaveHosts' );
00154         self::$_iMasterSlaveBalance        = $oConfig->getVar( 'iMasterSlaveBalance' );
00155         self::$_sAdminEmail                = $oConfig->getVar( 'sAdminEmail' );
00156         self::$_sLocalTimeFormat           = $oConfig->getVar( 'sLocalTimeFormat' );
00157         self::$_sLocalDateFormat           = $oConfig->getVar( 'sLocalDateFormat' );
00158     }
00159 
00167     protected static function _getConfigParam( $sConfigName )
00168     {
00169         if ( isset( self::$$sConfigName ) ) {
00170             return self::$$sConfigName;
00171         }
00172 
00173         return null;
00174     }
00175 
00181     public static function getInstance()
00182     {
00183         // disable caching for test modules
00184         if ( defined( 'OXID_PHP_UNIT' ) ) {
00185             self::$_instance = modInstances::getMod( __CLASS__ );
00186         }
00187 
00188         if ( !self::$_instance instanceof oxDb ) {
00189 
00190             //do not use simple oxNew here as it goes to eternal cycle
00191             self::$_instance = new oxDb();
00192 
00193             if ( defined( 'OXID_PHP_UNIT' ) ) {
00194                 modInstances::addMod( __CLASS__, self::$_instance);
00195             }
00196         }
00197         return self::$_instance;
00198     }
00199 
00205     protected function isAdmin()
00206     {
00207         return isAdmin();
00208     }
00209 
00215     protected function _getModules()
00216     {
00217         //adding exception handler for SQL errors
00218         if ( ( $_iDebug = self::_getConfigParam( '_iDebug' ) ) ) {
00219             include_once getShopBasePath() . 'core/adodblite/adodb-exceptions.inc.php';
00220         }
00221 
00222         $sModules = '';
00223         if (  $_iDebug == 2 || $_iDebug == 3 || $_iDebug == 4 || $_iDebug == 7  ) {
00224             $sModules = 'perfmon';
00225         }
00226 
00227         // log admin changes ?
00228         if ( $this->isAdmin() && self::_getConfigParam( '_blLogChangesInAdmin' ) ) {
00229             $sModules .= ( $sModules ? ':' : '' ) . 'oxadminlog';
00230         }
00231 
00232         return $sModules;
00233     }
00234 
00242     protected function _setUp( $oDb )
00243     {
00244         $_iDebug = self::_getConfigParam( '_iDebug' );
00245         if ( $_iDebug == 2 || $_iDebug == 3 || $_iDebug == 4  || $_iDebug == 7 ) {
00246             try {
00247                 $oDb->execute( 'truncate table adodb_logsql' );
00248             } catch ( ADODB_Exception $e ) {
00249                 // nothing
00250             }
00251             if ( method_exists( $oDb, "logSQL" ) ) {
00252                 $oDb->logSQL( true );
00253             }
00254         }
00255 
00256         $oDb->cacheSecs = 60 * 10; // 10 minute caching
00257         $oDb->execute( 'SET @@session.sql_mode = ""' );
00258 
00259         if ( self::_getConfigParam( '_iUtfMode' ) ) {
00260             $oDb->execute( 'SET NAMES "utf8"' );
00261             $oDb->execute( 'SET CHARACTER SET utf8' );
00262             $oDb->execute( 'SET CHARACTER_SET_CONNECTION = utf8' );
00263             $oDb->execute( 'SET CHARACTER_SET_DATABASE = utf8' );
00264             $oDb->execute( 'SET character_set_results = utf8' );
00265             $oDb->execute( 'SET character_set_server = utf8' );
00266         } elseif ( ( $sConn = self::_getConfigParam('_sDefaultDatabaseConnection') ) != '' ) {
00267             $oDb->execute( 'SET NAMES "' . $sConn . '"' );
00268         }
00269     }
00270 
00280     protected function _sendMail( $sEmail, $sSubject, $sBody )
00281     {
00282         include_once getShopBasePath() . 'core/phpmailer/class.phpmailer.php';
00283         $oMailer = new phpmailer();
00284         $oMailer->isMail();
00285 
00286         $oMailer->From = $sEmail;
00287         $oMailer->AddAddress( $sEmail );
00288         $oMailer->Subject = $sSubject;
00289         $oMailer->Body = $sBody;
00290         return $oMailer->send();
00291     }
00292 
00300     protected function _notifyConnectionErrors( $oDb )
00301     {
00302         // notifying shop owner about connection problems
00303         if ( ( $sAdminEmail = self::_getConfigParam( '_sAdminEmail' ) ) ) {
00304             $sFailedShop = isset( $_REQUEST['shp'] ) ? addslashes( $_REQUEST['shp'] ) : 'Base shop';
00305 
00306             $sDate = date( 'l dS of F Y h:i:s A');
00307             $sScript  = $_SERVER['SCRIPT_NAME'] . '?' . $_SERVER['QUERY_STRING'];
00308             $sReferer = $_SERVER['HTTP_REFERER'];
00309 
00310             //sending a message to admin
00311             $sWarningSubject = 'Offline warning!';
00312             $sWarningBody = "
00313                 Database error in OXID eShop:
00314                 Date: {$sDate}
00315                 Shop: {$sFailedShop}
00316 
00317                 mysql error: " . $oDb->errorMsg()."
00318                 mysql error no: " . $oDb->errorNo()."
00319 
00320                 Script: {$sScript}
00321                 Referer: {$sReferer}";
00322 
00323             $this->_sendMail( $sAdminEmail, $sWarningSubject, $sWarningBody );
00324         }
00325 
00326         //only exception to default construction method
00327         $oEx = new oxConnectionException();
00328         $oEx->setMessage( 'EXCEPTION_CONNECTION_NODB' );
00329         $oEx->setConnectionError( self::_getConfigParam( '_dbUser' ) . 's' . getShopBasePath() . $oDb->errorMsg() );
00330         throw $oEx;
00331     }
00332 
00341     protected function _onConnectionError( $oDb )
00342     {
00343         $sVerPrefix = '';
00344             $sVerPrefix = '_ce';
00345 
00346 
00347 
00348         $sConfig = join( '', file( getShopBasePath().'config.inc.php' ) );
00349 
00350         if ( strpos( $sConfig, '<dbHost'.$sVerPrefix.'>' ) !== false &&
00351              strpos( $sConfig, '<dbName'.$sVerPrefix.'>' ) !== false ) {
00352             // pop to setup as there is something wrong
00353             //oxRegistry::getUtils()->redirect( "setup/index.php", true, 302 );
00354             $sHeaderCode = "HTTP/1.1 302 Found";
00355             header( $sHeaderCode );
00356             header( "Location: setup/index.php" );
00357             header( "Connection: close" );
00358             exit();
00359         } else {
00360             // notifying about connection problems
00361             $this->_notifyConnectionErrors( $oDb );
00362 
00363         }
00364     }
00365 
00366 
00374     protected function _getDbInstance( $iInstType = false )
00375     {
00376         $sHost = self::_getConfigParam( "_dbHost" );
00377         $sUser = self::_getConfigParam( "_dbUser" );
00378         $sPwd  = self::_getConfigParam( "_dbPwd" );
00379         $sName = self::_getConfigParam( "_dbName" );
00380         $sType = self::_getConfigParam( "_dbType" );
00381 
00382         $oDb = ADONewConnection( $sType, $this->_getModules() );
00383 
00384 
00385             if ( !$oDb->connect( $sHost, $sUser, $sPwd, $sName ) ) {
00386                 $this->_onConnectionError( $oDb );
00387             }
00388 
00389         self::_setUp( $oDb );
00390 
00391         return $oDb;
00392     }
00393 
00403     public static function getDb( $iFetchMode = oxDb::FETCH_MODE_NUM )
00404     {
00405         if ( defined( 'OXID_PHP_UNIT' ) ) {
00406             if ( isset( modDB::$unitMOD ) && is_object( modDB::$unitMOD ) ) {
00407                 return modDB::$unitMOD;
00408             }
00409         }
00410 
00411         if ( self::$_oDB === null ) {
00412 
00413             $oInst = self::getInstance();
00414 
00415             //setting configuration on the first call
00416             $oInst->setConfig( oxRegistry::get("oxConfigFile") );
00417 
00418              global  $ADODB_SESSION_TBL,
00419                     $ADODB_SESSION_CONNECT,
00420                     $ADODB_SESSION_DRIVER,
00421                     $ADODB_SESSION_USER,
00422                     $ADODB_SESSION_PWD,
00423                     $ADODB_SESSION_DB,
00424                     $ADODB_SESS_LIFE,
00425                     $ADODB_SESS_DEBUG;
00426 
00427              // session related parameters. don't change.
00428 
00429             //Tomas
00430             //the default setting is 3000 * 60, but actually changing this will give no effect as now redefinition of this constant
00431             //appears after OXID custom settings are loaded and $ADODB_SESS_LIFE depends on user settings.
00432             //You can find the redefinition of ADODB_SESS_LIFE @ oxconfig.php:: line ~ 390.
00433             $ADODB_SESS_LIFE       = 3000 * 60;
00434             $ADODB_SESSION_TBL     = "oxsessions";
00435             $ADODB_SESSION_DRIVER  = self::_getConfigParam( '_dbType' );
00436             $ADODB_SESSION_USER    = self::_getConfigParam( '_dbUser' );
00437             $ADODB_SESSION_PWD     = self::_getConfigParam( '_dbPwd' );
00438             $ADODB_SESSION_DB      = self::_getConfigParam( '_dbName' );
00439             $ADODB_SESSION_CONNECT = self::_getConfigParam( '_dbHost' );
00440             $ADODB_SESS_DEBUG      = false;
00441 
00442             $oDb = new oxLegacyDb();
00443             $oDbInst = $oInst->_getDbInstance();
00444             $oDb->setConnection( $oDbInst );
00445 
00446             self::$_oDB = $oDb;
00447         }
00448 
00449         self::$_oDB->setFetchMode( $iFetchMode );
00450 
00451         return self::$_oDB;
00452     }
00453 
00461     public function quoteArray( $aStrArray )
00462     {
00463         $oDb = self::getDb();
00464 
00465         foreach ( $aStrArray as $sKey => $sString ) {
00466             $aStrArray[$sKey] = $oDb->quote( $sString );
00467         }
00468         return $aStrArray;
00469     }
00470 
00476     public function resetTblDescCache()
00477     {
00478         self::$_aTblDescCache = array();
00479     }
00480 
00488     public function getTableDescription( $sTableName )
00489     {
00490         // simple cache
00491         if ( isset( self::$_aTblDescCache[$sTableName] ) ) {
00492             return self::$_aTblDescCache[$sTableName];
00493         }
00494 
00495             $aFields = self::getDb()->MetaColumns( $sTableName );
00496 
00497         self::$_aTblDescCache[$sTableName] = $aFields;
00498 
00499         return $aFields;
00500     }
00501 
00513     public function convertDBDateTime( $oObject, $blToTimeStamp = false, $blOnlyDate = false )
00514     {
00515         return oxRegistry::get('oxUtilsDate')->convertDBDateTime( $oObject, $blToTimeStamp, $blOnlyDate );
00516     }
00517 
00528     public function convertDBTimestamp( $oObject, $blToTimeStamp = false )
00529     {
00530         return oxRegistry::get('oxUtilsDate')->convertDBTimestamp( $oObject, $blToTimeStamp );
00531     }
00532 
00543     public function convertDBDate( $oObject, $blToTimeStamp = false )
00544     {
00545         return oxRegistry::get('oxUtilsDate')->convertDBDate( $oObject, $blToTimeStamp );
00546     }
00547 
00556     public function isValidFieldName( $sField )
00557     {
00558         return ( boolean ) getStr()->preg_match( "#^[\w\d\._]*$#", $sField );
00559     }
00560 
00574     protected function _setDefaultFormatedValue( $oObject, $sDate, $sLocalDateFormat, $sLocalTimeFormat, $blOnlyDate )
00575     {
00576     }
00577 
00587     protected function _defineAndCheckDefaultTimeValues( $blToTimeStamp )
00588     {
00589     }
00590 
00600     protected function _defineAndCheckDefaultDateValues( $blToTimeStamp )
00601     {
00602     }
00603 
00611     protected function _defaultDatePattern()
00612     {
00613     }
00614 
00622     protected function _defaultTimePattern()
00623     {
00624     }
00625 
00633     protected function _regexp2ValidateDateInput()
00634     {
00635     }
00636 
00644     protected function _regexp2ValidateTimeInput()
00645     {
00646     }
00647 
00655     protected function _defineDateFormattingRules()
00656     {
00657         // date formatting rules
00658         $aDFormats  = array("ISO" => array("Y-m-d", array(2, 3, 1), "0000-00-00"),
00659                             "EUR" => array("d.m.Y", array(2, 1, 3), "00.00.0000"),
00660                             "USA" => array("m/d/Y", array(1, 2, 3), "00/00/0000")
00661                            );
00662         return $aDFormats;
00663     }
00664 
00672     protected function _defineTimeFormattingRules()
00673     {
00674         // time formatting rules
00675         $aTFormats  = array("ISO" => array("H:i:s",   array(1, 2, 3 ), "00:00:00"),
00676                             "EUR" => array("H.i.s",   array(1, 2, 3 ), "00.00.00"),
00677                             "USA" => array("h:i:s A", array(1, 2, 3 ), "00:00:00 AM")
00678                            );
00679         return $aTFormats;
00680     }
00681 
00694     protected function _setDefaultDateTimeValue( $oObject, $sLocalDateFormat, $sLocalTimeFormat, $blOnlyDate )
00695     {
00696         $aDFormats  = $this->_defineDateFormattingRules();
00697         $aTFormats  = $this->_defineTimeFormattingRules();
00698 
00699         $sReturn = $aDFormats[$sLocalDateFormat][2];
00700         if ( !$blOnlyDate) {
00701             $sReturn .= " ".$aTFormats[$sLocalTimeFormat][2];
00702         }
00703 
00704         if ($oObject instanceof oxField) {
00705             $oObject->setValue(trim($sReturn));
00706         } else {
00707             $oObject->value = trim($sReturn);
00708         }
00709         // increasing(decreasing) field length
00710         $oObject->fldmax_length = strlen( $oObject->value);
00711     }
00712 
00725     protected function _setDate( $oObject, $sDateFormat, $aDFields, $aDateMatches )
00726     {
00727         // formatting correct time value
00728         $iTimestamp = mktime( 0, 0, 0, $aDateMatches[$aDFields[0]],
00729                               $aDateMatches[$aDFields[1]],
00730                               $aDateMatches[$aDFields[2]]);
00731 
00732         if ($oObject instanceof oxField) {
00733             $oObject->setValue(@date( $sDateFormat, $iTimestamp ));
00734         } else {
00735             $oObject->value = @date( $sDateFormat, $iTimestamp );
00736         }
00737         // we should increase (decrease) field length
00738         $oObject->fldmax_length = strlen( $oObject->value );
00739     }
00740 
00756     protected function _formatCorrectTimeValue( $oObject, $sDateFormat, $sTimeFormat, $aDateMatches, $aTimeMatches, $aTFields, $aDFields )
00757     {
00758         // formatting correct time value
00759         $iTimestamp = @mktime( (int) $aTimeMatches[$aTFields[0]],
00760                                (int) $aTimeMatches[$aTFields[1]],
00761                                (int) $aTimeMatches[$aTFields[2]],
00762                                (int) $aDateMatches[$aDFields[0]],
00763                                (int) $aDateMatches[$aDFields[1]],
00764                                (int) $aDateMatches[$aDFields[2]] );
00765 
00766         if ($oObject instanceof oxField) {
00767             $oObject->setValue(trim( @date( $sDateFormat." ".$sTimeFormat, $iTimestamp ) ));
00768         } else {
00769             $oObject->value = trim( @date( $sDateFormat." ".$sTimeFormat, $iTimestamp ) );
00770         }
00771 
00772         // we should increase (decrease) field length
00773         $oObject->fldmax_length = strlen( $oObject->value );
00774     }
00775 
00781     protected function _getConnectionId()
00782     {
00783         return self::getDb()->getDb()->connectionId;
00784     }
00785 
00793     public function escapeString( $sString )
00794     {
00795         if ( 'mysql' == self::_getConfigParam( "_dbType" )) {
00796             return mysql_real_escape_string( $sString, $this->_getConnectionId() );
00797         } elseif ( 'mysqli' == self::_getConfigParam( "_dbType" )) {
00798             return mysqli_real_escape_string( $this->_getConnectionId(), $sString );
00799         } else {
00800             return mysql_real_escape_string( $sString, $this->_getConnectionId() );
00801         }
00802     }
00803 
00813     public function updateViews( $aTables = null )
00814     {
00815         $oMetaData = oxNew('oxDbMetaDataHandler');
00816         return $oMetaData->updateViews();
00817     }
00818 }