oxdb.php

Go to the documentation of this file.
00001 <?php
00002 
00006 class oxDb extends oxSuperCfg
00007 {
00013     private static $_instance = null;
00014 
00020     private static  $_oDB = null;
00021 
00027     protected static $_aTblDescCache = array();
00028 
00034     public static function getInstance()
00035     {
00036         // disable caching for test modules
00037         if ( defined( 'OXID_PHP_UNIT' ) ) {
00038             static $inst = array();
00039             self::$_instance = $inst[oxClassCacheKey()];
00040         }
00041 
00042 
00043         if ( !self::$_instance instanceof oxDb ) {
00044 
00045             //do not use simple oxNew here as it goes to eternal cycle
00046             self::$_instance = oxNew( 'oxdb' );
00047 
00048             if ( defined( 'OXID_PHP_UNIT' ) ) {
00049                 $inst[oxClassCacheKey()] = self::$_instance;
00050             }
00051         }
00052         return self::$_instance;
00053     }
00054 
00064     public static function getDb( $blAssoc = false )
00065     {
00066         if ( defined( 'OXID_PHP_UNIT' ) ) {
00067             if ( isset( modDB::$unitMOD ) && is_object( modDB::$unitMOD ) ) {
00068                 return modDB::$unitMOD;
00069             }
00070         }
00071 
00072         global  $ADODB_FETCH_MODE;
00073 
00074         if ( $blAssoc )
00075             $ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;
00076         else
00077             $ADODB_FETCH_MODE = ADODB_FETCH_NUM;
00078 
00079         if ( self::$_oDB !== null ) {
00080             return self::$_oDB;
00081         }
00082 
00083         global  $ADODB_CACHE_DIR;
00084         global  $ADODB_DRIVER,
00085                 $ADODB_SESSION_TBL,
00086                 $ADODB_SESSION_CONNECT,
00087                 $ADODB_SESSION_DRIVER,
00088                 $ADODB_SESSION_USER,
00089                 $ADODB_SESSION_PWD,
00090                 $ADODB_SESSION_DB,
00091                 $ADODB_SESS_LIFE,
00092                 $ADODB_SESS_DEBUG;
00093 
00094         //adding exception handler for SQL errors
00095         $myConfig = self::getInstance()->getConfig();
00096         $iDebug = $myConfig->getConfigParam( 'iDebug' );
00097         if ( $iDebug ) {
00098             require_once getShopBasePath() . 'core/adodblite/adodb-exceptions.inc.php';
00099         }
00100 
00101         // session related parameters. don't change.
00102 
00103         //Tomas
00104         //the default setting is 3000 * 60, but actually changing this will give no effect as now redefinition of this constant
00105         //appears after OXID custom settings are loaded and $ADODB_SESS_LIFE depends on user settings.
00106         //You can find the redefinition of ADODB_SESS_LIFE @ oxconfig.php:: line ~ 390.
00107         $ADODB_SESS_LIFE       = 3000 * 60;
00108         $ADODB_SESSION_TBL     = "oxsessions";
00109         $ADODB_SESSION_DRIVER  = $ADODB_DRIVER;
00110         $ADODB_SESSION_USER    = $myConfig->getConfigParam( 'dbUser' );
00111         $ADODB_SESSION_PWD     = $myConfig->getConfigParam( 'dbPwd' );
00112         $ADODB_SESSION_DB      = $myConfig->getConfigParam( 'dbName' );
00113         $ADODB_SESSION_CONNECT = $myConfig->getConfigParam( 'dbHost' );
00114         $ADODB_SESS_DEBUG      = false;
00115         $ADODB_CACHE_DIR       = $myConfig->getConfigParam( 'sCompileDir' );
00116 
00117         $sModules = '';
00118         if (  $iDebug == 2 || $iDebug == 3 || $iDebug == 4 || $iDebug == 7  ) {
00119             $sModules = 'perfmon';
00120         }
00121 
00122         // log admin changes ?
00123         if ( $myConfig->isAdmin() && $myConfig->getConfigParam( 'blLogChangesInAdmin' ) ) {
00124             $sModules = ( $sModules ? ':' : '' ) . 'oxadminlog';
00125         }
00126 
00127         self::$_oDB = ADONewConnection( $myConfig->getConfigParam( 'dbType' ), $sModules );
00128 
00129         $sVerPrefix = '';
00130             $sVerPrefix = '_ce';
00131 
00132         if ( !self::$_oDB->connect( $myConfig->getConfigParam( 'dbHost' ), $myConfig->getConfigParam( 'dbUser' ), $myConfig->getConfigParam( 'dbPwd' ), $myConfig->getConfigParam( 'dbName' ) ) ) {
00133             $sConfig = join( '', file( getShopBasePath().'config.inc.php' ) );
00134             if ( strpos( $sConfig, '<dbHost'.$sVerPrefix.'>' ) !== false &&
00135                  strpos( $sConfig, '<dbName'.$sVerPrefix.'>' ) !== false ) {
00136                 header( 'location:setup/index.php' ); // pop to setup as there is something wrong
00137                 exit();
00138             } else {
00139 
00140                 // notifying shop owner about connection problems
00141                 $sFailedShop = isset( $_REQUEST['shp'] )?addslashes( $_REQUEST['shp'] ):'Base shop';
00142 
00143                 $sDate = date( 'l dS of F Y h:i:s A');
00144                 $sScript  = $_SERVER['SCRIPT_NAME'].'?'.$_SERVER['QUERY_STRING'];
00145                 $sReferer = $_SERVER['HTTP_REFERER'];
00146 
00147                 //sending a message to admin
00148                 $sWarningSubject = 'Offline warning!';
00149                 $sWarningBody = "
00150                 Database error in OXID eShop:
00151                 Date: $sDate
00152                 Shop: $sFailedShop
00153 
00154                 mysql error: ".self::$_oDB->errorMsg()."
00155                 mysql error no: ".self::$_oDB->errorNo()."
00156 
00157                 Script: $sScript
00158                 Referer: $sReferer";
00159 
00160                 if ( ( $sAdminEmail = $myConfig->getConfigParam( 'sAdminEmail' ) ) ) {
00161                     include 'core/phpmailer/class.phpmailer.php';
00162 
00163                     $oMailer = new phpmailer();
00164                     $oMailer->isMail();
00165                     $oMailer->From = $sAdminEmail;
00166                     $oMailer->AddAddress( $sAdminEmail );
00167                     $oMailer->Subject = $sWarningSubject;
00168                     $oMailer->Body = $sWarningBody;
00169                     $oMailer->send();
00170                 }
00171 
00172                 //only exception to default construction method
00173                 $oEx = new oxConnectionException();
00174                 $oEx->setMessage( 'EXCEPTION_CONNECTION_NODB' );
00175                 $oEx->setConnectionError( $myConfig->getConfigParam( 'dbUser' ).'s'.getShopBasePath().self::$_oDB->errorMsg() );
00176                 throw $oEx;
00177             }
00178         }
00179 
00180         if (  $iDebug == 2 || $iDebug == 3 || $iDebug == 4  || $iDebug == 7 ) {
00181             try {
00182                 self::$_oDB->execute('truncate table adodb_logsql;');
00183             } catch (ADODB_Exception $e) {
00184                 // nothing
00185             }
00186             self::$_oDB->logSQL( true );
00187         }
00188 
00189         self::$_oDB->cacheSecs = 60 * 10; // 10 minute caching
00190         self::$_oDB->execute( 'SET @@session.sql_mode = ""' );
00191 
00192         return self::$_oDB;
00193     }
00194 
00202     public function getMultiLangFieldName( $sField )
00203     {
00204         /*
00205         $sLangAdd = $this->getConfig()->getShopLanguage();
00206         if ( $sLangAdd ) {
00207             $sField .= '_'.$sLangAdd;
00208         }*/
00209 
00210         return $sField . oxLang::getInstance()->getLanguageTag();
00211     }
00212 
00221     public function isQuoteNeeded( $sFieldtype)
00222     {
00223         $aTypesWoQuotes = array('int', 'decimal', 'float', 'tinyint', 'smallint', 'mediumint', 'bigint', 'double');
00224         return !in_array( $sFieldtype, $aTypesWoQuotes);
00225     }
00226 
00234     public function getTableDescription( $sTableName )
00235     {
00236         // simple cache
00237         if ( isset( self::$_aTblDescCache[$sTableName] ) ) {
00238             return self::$_aTblDescCache[$sTableName];
00239         }
00240 
00241             $aFields = self::getDb()->MetaColumns( $sTableName );
00242 
00243         self::$_aTblDescCache[$sTableName] = $aFields;
00244 
00245         return $aFields;
00246     }
00247 
00257     public function convertDBDateTime( $oObject, $blToTimeStamp = false, $blOnlyDate = false )
00258     {
00259         $sDate = $oObject->value;
00260 
00261         // defining time format
00262         $sLocalDateFormat = $this->_defineAndCheckDefaultDateValues( $blToTimeStamp );
00263         $sLocalTimeFormat = $this->_defineAndCheckDefaultTimeValues( $blToTimeStamp );
00264 
00265         // default date/time patterns
00266         $aDefDatePatterns = $this->_defaultDatePattern();
00267 
00268         // regexps to validate input
00269         $aDatePatterns = $this->_regexp2ValidateDateInput();
00270         $aTimePatterns = $this->_regexp2ValidateTimeInput();
00271 
00272         // date/time formatting rules
00273         $aDFormats  = $this->_defineDateFormattingRules();
00274         $aTFormats  = $this->_defineTimeFormattingRules();
00275 
00276         // empty date field value ? setting default value
00277         if ( !$sDate) {
00278             $this->_setDefaultDateTimeValue($oObject, $sLocalDateFormat, $sLocalTimeFormat, $blOnlyDate);
00279             return $oObject->value;
00280         }
00281 
00282         $blDefDateFound = false;
00283 
00284         // looking for default values that are formatted by MySQL
00285         foreach ( array_keys( $aDefDatePatterns ) as $sDefDatePattern ) {
00286             if ( preg_match( $sDefDatePattern, $sDate)) {
00287                 $blDefDateFound = true;
00288                 break;
00289             }
00290         }
00291 
00292         // default value is set ?
00293         if ( $blDefDateFound) {
00294             $this->_setDefaultFormatedValue($oObject, $sDate, $sLocalDateFormat, $sLocalTimeFormat, $blOnlyDate);
00295             return $oObject->value;
00296         }
00297 
00298         $blDateFound = false;
00299         $blTimeFound = false;
00300         $aDateMatches = array();
00301         $aTimeMatches = array();
00302 
00303         // looking for date field
00304         foreach ( $aDatePatterns as $sPattern => $sType) {
00305             if ( preg_match( $sPattern, $sDate, $aDateMatches)) {
00306                 $blDateFound = true;
00307 
00308                 // now we know the type of passed date
00309                 $sDateFormat = $aDFormats[$sLocalDateFormat][0];
00310                 $aDFields    = $aDFormats[$sType][1];
00311                 break;
00312             }
00313         }
00314 
00315         // no such date field available ?
00316         if ( !$blDateFound) {
00317             return $sDate;
00318         }
00319 
00320         if ( $blOnlyDate) {
00321             $this->_setDate($oObject, $sDateFormat, $aDFields, $aDateMatches);
00322             return $oObject->value;
00323         }
00324 
00325         // looking for time field
00326         foreach ( $aTimePatterns as $sPattern => $sType) {
00327             if ( preg_match( $sPattern, $sDate, $aTimeMatches)) {
00328                 $blTimeFound = true;
00329 
00330                 // now we know the type of passed time
00331                 $sTimeFormat = $aTFormats[$sLocalTimeFormat][0];
00332                 $aTFields    = $aTFormats[$sType][1];
00333 
00334                 //
00335                 if ( $sType == "USA" && isset($aTimeMatches[4])) {
00336                     $iIntVal = (int) $aTimeMatches[1];
00337                     if ( $aTimeMatches[4] == "PM") {
00338                         if ( $iIntVal < 13) {
00339                             $iIntVal += 12;
00340                         }
00341                     } elseif ( $aTimeMatches[4] == "AM" && $aTimeMatches[1] == "12") {
00342                         $iIntVal = 0;
00343                     }
00344 
00345                     $aTimeMatches[1] = sprintf("%02d", $iIntVal);
00346                 }
00347 
00348                 break;
00349             }
00350         }
00351 
00352         if ( !$blTimeFound) {
00353             //return $sDate;
00354             // #871A. trying to keep date as possible correct
00355             $this->_setDate($oObject, $sDateFormat, $aDFields, $aDateMatches);
00356             return $oObject->value;
00357         }
00358 
00359         $this->_formatCorrectTimeValue($oObject, $sDateFormat, $sTimeFormat, $aDateMatches, $aTimeMatches, $aTFields, $aDFields);
00360 
00361         // on some cases we get empty value
00362         if ( !$oObject->fldmax_length) {
00363             return $this->convertDBDateTime( $oObject, $blToTimeStamp, $blOnlyDate);
00364         }
00365         return $oObject->value;
00366     }
00367 
00376     public function convertDBTimestamp( $oObject, $blToTimeStamp = false )
00377     {
00378          // on this case usually means that we gonna save value, and value is formatted, not plain
00379         $sSQLTimeStampPattern = "/^([0-9]{4})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})$/";
00380         $sISOTimeStampPattern = "/^([0-9]{4})-([0-9]{2})-([0-9]{2}) ([0-9]{2}):([0-9]{2}):([0-9]{2})$/";
00381         $aMatches = array();
00382 
00383         // preparing value to save
00384         if ( $blToTimeStamp) {
00385             // reformatting value to ISO
00386             $this->convertDBDateTime( $oObject, $blToTimeStamp );
00387 
00388             if ( preg_match( $sISOTimeStampPattern, $oObject->value, $aMatches)) {
00389                 // changing layout
00390                 $oObject->setValue($aMatches[1].$aMatches[2].$aMatches[3].$aMatches[4].$aMatches[5].$aMatches[6]);
00391                 $oObject->fldmax_length = strlen( $oObject->value);
00392                 return $oObject->value;
00393             }
00394         } else {
00395             // loading and formatting value
00396             // checking and parsing SQL timestamp value
00397             //$sSQLTimeStampPattern = "/^([0-9]{4})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})$/";
00398             if ( preg_match( $sSQLTimeStampPattern, $oObject->value, $aMatches ) ) {
00399                 $iTimestamp = mktime( $aMatches[4], //h
00400                                         $aMatches[5], //m
00401                                         $aMatches[6], //s
00402                                         $aMatches[2], //M
00403                                         $aMatches[3], //d
00404                                         $aMatches[1]); //y
00405                 if ( !$iTimestamp ) {
00406                     $iTimestamp = "0";
00407                 }
00408 
00409                 $oObject->setValue(trim( date( "Y-m-d H:i:s", $iTimestamp)));
00410                 $oObject->fldmax_length = strlen( $oObject->value);
00411                 $this->convertDBDateTime( $oObject, $blToTimeStamp );
00412                 return $oObject->value;
00413             }
00414         }
00415     }
00416 
00425     public function convertDBDate( $oObject, $blToTimeStamp = false )
00426     {
00427         return $this->convertDBDateTime( $oObject, $blToTimeStamp, true );
00428     }
00429 
00437     public function createSQLList( $aArray )
00438     {
00439         $sRet = "";
00440 
00441         $blSep = false;
00442         foreach ( $aArray as $aToken) {
00443             if ( !$aToken[0]) {
00444                 continue;
00445             }
00446             if ( $blSep) {
00447                 $sRet .= ",";
00448             }
00449             $sRet .= "'".$aToken[0]."'";
00450             $blSep = true;
00451         }
00452         return $sRet;
00453     }
00454 
00460     static public function startTransaction()
00461     {
00462         self::$_oDB->execute( 'START TRANSACTION' );
00463     }
00464 
00470     static public function commitTransaction()
00471     {
00472         self::$_oDB->execute( 'COMMIT' );
00473     }
00474 
00480     static public function rollbackTransaction()
00481     {
00482         self::$_oDB->execute( 'ROLLBACK' );
00483     }
00484 
00493     static public function setTransactionIsolationLevel( $sLevel = null )
00494     {
00495         $aLevels = array( 'READ UNCOMMITTED', 'READ COMMITTED', 'REPEATABLE READ', 'SERIALIZABLE' );
00496 
00497         if (in_array(strtoupper($sLevel), $aLevels)) {
00498             self::$_oDB->execute( 'SET TRANSACTION ISOLATION LEVEL ' . $sLevel );
00499         }
00500     }
00501 
00502 
00511     public function isValidFieldName( $sField )
00512     {
00513         return ( boolean ) preg_match( "#^[\w\d\._]*$#", $sField );
00514     }
00515 
00527     protected function _setDefaultFormatedValue( $oObject, $sDate, $sLocalDateFormat, $sLocalTimeFormat, $blOnlyDate )
00528     {
00529         $aDefTimePatterns = $this->_defaultTimePattern();
00530         $aDFormats  = $this->_defineDateFormattingRules();
00531         $aTFormats  = $this->_defineTimeFormattingRules();
00532 
00533         foreach ( array_keys( $aDefTimePatterns ) as $sDefTimePattern ) {
00534             if ( preg_match( $sDefTimePattern, $sDate ) ) {
00535                 $blDefTimeFound = true;
00536                 break;
00537             }
00538         }
00539 
00540         // setting and returning default formatted value
00541         if ( $blOnlyDate) {
00542             $oObject->setValue(trim( $aDFormats[$sLocalDateFormat][2] ));// . " " . @$aTFormats[$sLocalTimeFormat][2]);
00543             // increasing(decreasing) field lenght
00544             $oObject->fldmax_length = strlen( $oObject->value );
00545             return ;
00546         } elseif ( $blDefTimeFound ) {
00547             // setting value
00548             $oObject->setValue(trim( $aDFormats[$sLocalDateFormat][2] . " " . $aTFormats[$sLocalTimeFormat][2] ));
00549             // increasing(decreasing) field lenght
00550             $oObject->fldmax_length = strlen( $oObject->value );
00551             return ;
00552         }
00553     }
00554 
00562     protected function _defineAndCheckDefaultTimeValues( $blToTimeStamp )
00563     {
00564         // defining time format
00565         // checking for default values
00566         $sLocalTimeFormat = $this->getConfig()->getConfigParam( 'sLocalTimeFormat' );
00567         if ( !$sLocalTimeFormat || $blToTimeStamp) {
00568             $sLocalTimeFormat = "ISO";
00569         }
00570         return $sLocalTimeFormat;
00571     }
00572 
00580     protected function _defineAndCheckDefaultDateValues( $blToTimeStamp )
00581     {
00582         // defining time format
00583         // checking for default values
00584         $sLocalDateFormat = $this->getConfig()->getConfigParam( 'sLocalDateFormat' );
00585         if ( !$sLocalDateFormat || $blToTimeStamp) {
00586             $sLocalDateFormat = "ISO";
00587         }
00588         return $sLocalDateFormat;
00589     }
00590 
00596     protected function _defaultDatePattern()
00597     {
00598         // default date patterns
00599         $aDefDatePatterns = array("/^0000-00-00/"   => "ISO",
00600                                   "/^00\.00\.0000/" => "EUR",
00601                                   "/^00\/00\/0000/" => "USA"
00602                                  );
00603         return $aDefDatePatterns;
00604     }
00605 
00611     protected function _defaultTimePattern()
00612     {
00613         // default time patterns
00614         $aDefTimePatterns = array("/00:00:00$/"    => "ISO",
00615                                   "/00\.00\.00$/"  => "EUR",
00616                                   "/00:00:00 AM$/" => "USA"
00617                                  );
00618         return $aDefTimePatterns;
00619     }
00620 
00626     protected function _regexp2ValidateDateInput()
00627     {
00628         // regexps to validate input
00629         $aDatePatterns = array("/^([0-9]{4})-([0-9]{2})-([0-9]{2})/"   => "ISO",
00630                                "/^([0-9]{2})\.([0-9]{2})\.([0-9]{4})/" => "EUR",
00631                                "/^([0-9]{2})\/([0-9]{2})\/([0-9]{4})/" => "USA"
00632                               );
00633         return $aDatePatterns;
00634     }
00635 
00641     protected function _regexp2ValidateTimeInput()
00642     {
00643         // regexps to validate input
00644         $aTimePatterns = array("/([0-9]{2}):([0-9]{2}):([0-9]{2})$/"   => "ISO",
00645                                "/([0-9]{2})\.([0-9]{2})\.([0-9]{2})$/" => "EUR",
00646                                "/([0-9]{2}):([0-9]{2}):([0-9]{2}) ([AP]{1}[M]{1})$/" => "USA"
00647                               );
00648         return $aTimePatterns;
00649     }
00650 
00656     protected function _defineDateFormattingRules()
00657     {
00658         // date formatting rules
00659         $aDFormats  = array("ISO" => array("Y-m-d", array(2, 3, 1), "0000-00-00"),
00660                             "EUR" => array("d.m.Y", array(2, 1, 3), "00.00.0000"),
00661                             "USA" => array("m/d/Y", array(1, 2, 3), "00/00/0000")
00662                            );
00663         return $aDFormats;
00664     }
00665 
00671     protected function _defineTimeFormattingRules()
00672     {
00673         // time formatting rules
00674         $aTFormats  = array("ISO" => array("H:i:s",   array(1, 2, 3 ), "00:00:00"),
00675                             "EUR" => array("H.i.s",   array(1, 2, 3 ), "00.00.00"),
00676                             "USA" => array("h:i:s A", array(1, 2, 3 ), "00:00:00 AM")
00677                            );
00678         return $aTFormats;
00679     }
00680 
00691     protected function _setDefaultDateTimeValue( $oObject, $sLocalDateFormat, $sLocalTimeFormat, $blOnlyDate )
00692     {
00693         $aDFormats  = $this->_defineDateFormattingRules();
00694         $aTFormats  = $this->_defineTimeFormattingRules();
00695 
00696         $sReturn = $aDFormats[$sLocalDateFormat][2];
00697         if ( !$blOnlyDate) {
00698             $sReturn .= " ".$aTFormats[$sLocalTimeFormat][2];
00699         }
00700 
00701         if ($oObject instanceof oxField) {
00702             $oObject->setValue(trim($sReturn));
00703         } else {
00704             $oObject->value = trim($sReturn);
00705         }
00706         // increasing(decreasing) field lenght
00707         $oObject->fldmax_length = strlen( $oObject->value);
00708     }
00709 
00720     protected function _setDate( $oObject, $sDateFormat, $aDFields, $aDateMatches )
00721     {
00722         // formatting correct time value
00723         $iTimestamp = mktime( 0, 0, 0, $aDateMatches[$aDFields[0]],
00724                               $aDateMatches[$aDFields[1]],
00725                               $aDateMatches[$aDFields[2]]);
00726 
00727         if ($oObject instanceof oxField) {
00728             $oObject->setValue(@date( $sDateFormat, $iTimestamp ));
00729         } else {
00730             $oObject->value = @date( $sDateFormat, $iTimestamp );
00731         }
00732         // we should increase (decrease) field lenght
00733         $oObject->fldmax_length = strlen( $oObject->value );
00734     }
00735 
00749     protected function _formatCorrectTimeValue( $oObject, $sDateFormat, $sTimeFormat, $aDateMatches, $aTimeMatches, $aTFields, $aDFields )
00750     {
00751         // formatting correct time value
00752         $iTimestamp = @mktime( (int) $aTimeMatches[$aTFields[0]],
00753                                (int) $aTimeMatches[$aTFields[1]],
00754                                (int) $aTimeMatches[$aTFields[2]],
00755                                (int) $aDateMatches[$aDFields[0]],
00756                                (int) $aDateMatches[$aDFields[1]],
00757                                (int) $aDateMatches[$aDFields[2]] );
00758 
00759         if ($oObject instanceof oxField) {
00760             $oObject->setValue(trim( @date( $sDateFormat." ".$sTimeFormat, $iTimestamp ) ));
00761         } else {
00762             $oObject->value = trim( @date( $sDateFormat." ".$sTimeFormat, $iTimestamp ) );
00763         }
00764 
00765         // we should increase (decrease) field lenght
00766         $oObject->fldmax_length = strlen( $oObject->value );
00767     }
00768 
00769 }

Generated on Thu Dec 4 12:04:56 2008 for OXID eShop CE by  doxygen 1.5.5