oxbase.php

Go to the documentation of this file.
00001 <?php
00002 
00006 DEFINE('ACTION_NA', 0);
00007 DEFINE('ACTION_DELETE', 1);
00008 DEFINE('ACTION_INSERT', 2);
00009 DEFINE('ACTION_UPDATE', 3);
00010 DEFINE('ACTION_UPDATE_STOCK', 4);
00011 
00016 class oxBase extends oxSuperCfg
00017 {
00022     protected $_sOXID = null;
00023 
00028     protected $_iShopId = null;
00029 
00035     protected $_blIsSimplyClonable = true;
00036 
00044     protected $_aErrors = array();
00045 
00050     protected $_sClassName = 'oxbase';
00051 
00057     protected $_sCoreTable = null;
00058 
00063     protected $_sViewTable  = null;
00064 
00065 
00071     protected $_aFieldNames = array('oxid' => 0);
00072 
00077     protected $_blIsNewCache = false;
00078 
00084     protected $_sCacheKey = null;
00085 
00091     protected $_blUseLazyLoading = false;
00092 
00098     protected $_aSkipSaveFields = array();
00099 
00104     protected $_sExistKey = "oxid";
00105 
00112     protected $_blIsDerived = null;
00113 
00123     protected static $_blDisableFieldCaching = array();
00124 
00130     protected $_blIsSeoObject = false;
00131 
00137     protected $_blReadOnly = false;
00138 
00144     protected $_blIsInList = false;
00145 
00151     protected $_isLoaded = false;
00152 
00158     protected $_aInnerLazyCache = null;
00159 
00163     public function __construct()
00164     {
00165         // set active shop
00166         $myConfig = $this->getConfig();
00167         $this->_sCacheKey = $this->getViewName();
00168         if ( $this->_blUseLazyLoading ) {
00169             $this->_sCacheKey .= $myConfig->getActiveView()->getClassName();
00170         } else {
00171             $this->_sCacheKey .= "allviews";
00172         }
00173 
00174         //do not cache for admin?
00175         if ( $this->isAdmin() ) {
00176             $this->_sCacheKey = null;
00177         }
00178 
00179         $this->setShopId( $myConfig->getShopId() );
00180     }
00181 
00190     public function __set( $sName, $sValue )
00191     {
00192         $this->$sName = $sValue;
00193         if ( $this->_blUseLazyLoading && strpos( $sName, $this->_sCoreTable . "__" ) === 0 ) {
00194             $sFieldName = str_replace( $this->_sCoreTable . "__", '', $sName );
00195             if ( $sFieldName != 'oxnid' && ( !isset( $this->_aFieldNames[$sFieldName] ) || !$this->_aFieldNames[$sFieldName] ) ) {
00196                 $aAllFields = $this->_getAllFields(true);
00197                 if ( isset( $aAllFields[strtolower($sFieldName)] ) ) {
00198                     $iFieldStatus = $this->_getFieldStatus( $sFieldName );
00199                     $this->_addField( $sFieldName, $iFieldStatus );
00200                 }
00201             }
00202         }
00203     }
00204 
00212     public function __get( $sName )
00213     {
00214         switch ( $sName ) {
00215             case 'blIsDerived':
00216                 return $this->isDerived();
00217                 break;
00218             case 'sOXID':
00219                 return $this->getId();
00220                 break;
00221             case 'blReadOnly':
00222                 return $this->isReadOnly();
00223                 break;
00224         }
00225 
00226 
00227 
00228         // implementing lazy loading fields
00229         // This part of the code is slow and normally is called before field cache is built.
00230         // Make sure it is not called after first page is loaded and cache data is fully built.
00231         if ( $this->_blUseLazyLoading && stripos( $sName, $this->_sCoreTable . "__" ) === 0 ) {
00232 
00233             if ( $this->getId() ) {
00234 
00235                 //lazy load it
00236                 $sFieldName      = str_replace( $this->_sCoreTable . "__", '', $sName );
00237                 $sCacheFieldName = strtoupper( $sFieldName );
00238 
00239                 $iFieldStatus = $this->_getFieldStatus( $sFieldName );
00240                 $sViewName    = $this->getViewName();
00241                 $sId = $this->getId();
00242 
00243                 try {
00244                     if ( $this->_aInnerLazyCache === null ) {
00245 
00246                         $oDb = oxDb::getDb( true );
00247                         $sQ = "SELECT * FROM " . $sViewName . " WHERE `oxid` = " . $oDb->quote( $sId );
00248                         $rs = $oDb->execute( $sQ );
00249                         if ( $rs ) {
00250                             $this->_aInnerLazyCache = $rs->fields;
00251                             if ( array_key_exists( $sCacheFieldName, $rs->fields ) ) {
00252                                 $sFieldValue = $rs->fields[$sCacheFieldName];
00253                             } else {
00254                                 return null;
00255                             }
00256                         } else {
00257                             return null;
00258                         }
00259                     } elseif ( array_key_exists( $sCacheFieldName, $this->_aInnerLazyCache ) ) {
00260                         $sFieldValue = $this->_aInnerLazyCache[$sCacheFieldName];
00261                     } else {
00262                         return null;
00263                     }
00264 
00265                     $this->_addField( $sFieldName, $iFieldStatus );
00266                     $this->_setFieldData( $sFieldName, $sFieldValue );
00267 
00268                     //save names to cache for next loading
00269                     if ($this->_sCacheKey) {
00270                         $myUtils = oxUtils::getInstance();
00271                         $sCacheKey = 'fieldnames_' . $this->_sCoreTable . "_" . $this->_sCacheKey;
00272                         $aFieldNames = $myUtils->fromFileCache( $sCacheKey );
00273                         $aFieldNames[$sFieldName] = $iFieldStatus;
00274                         $myUtils->toFileCache( $sCacheKey, $aFieldNames );
00275                     }
00276                 } catch ( Exception $e ) {
00277                     return null;
00278                 }
00279 
00280                 //do not use field cache for this page
00281                 //as if we use it for lists then objects are loaded empty instead of lazy loading.
00282                 self::$_blDisableFieldCaching[get_class( $this )] = true;
00283             }
00284 
00285             oxUtilsObject::getInstance()->resetInstanceCache(get_class($this));
00286         }
00287 
00288         //returns oxStdClass implementing __toString() method due to uknown scenario where this var should be used.
00289         if (!isset( $this->$sName ) ) {
00290             $this->$sName = null;
00291         }
00292 
00293         return $this->$sName;
00294     }
00295 
00303     public function __isset($mVar)
00304     {
00305         return isset($this->$mVar);
00306     }
00307 
00313     public function __clone()
00314     {
00315         if (!$this->_blIsSimplyClonable) {
00316             foreach ( $this->_aFieldNames as $sField => $sVal ) {
00317                 $sLongName = $this->_getFieldLongName( $sField );
00318                 if ( is_object($this->$sLongName)) {
00319                     $this->$sLongName = clone $this->$sLongName;
00320                 }
00321             }
00322         }
00323     }
00324 
00332     public function oxClone($oObject)
00333     {
00334         $aClasVars = get_object_vars( $oObject);
00335         while (list($name, $value) = each($aClasVars)) {
00336             if ( is_object( $oObject->$name ) ) {
00337                 $this->$name = clone $oObject->$name;
00338             } else {
00339                 $this->$name = $oObject->$name;
00340             }
00341         }
00342     }
00343 
00352     public function init( $sTableName = null, $blForceAllFields = false)
00353     {
00354 
00355         if ( !$sTableName ) {
00356             $sTableName = $this->_sCoreTable;
00357         } else {
00358             $this->_sCoreTable = $sTableName;
00359         }
00360 
00361         // reset view table
00362         $this->_sViewTable = false;
00363 
00364         if ( count( $this->_aFieldNames ) <= 1 ) {
00365             $this->_initDataStructure( $blForceAllFields );
00366         }
00367     }
00368 
00376     public function assign( $dbRecord )
00377     {
00378         if ( !is_array( $dbRecord ) ) {
00379             return;
00380         }
00381 
00382 
00383         reset($dbRecord );
00384         while ( list( $sName, $sValue ) = each( $dbRecord ) ) {
00385 
00386             // patch for IIS
00387             //TODO: test it on IIS do we still need it
00388             //if( is_array($value) && count( $value) == 1)
00389             //    $value = current( $value);
00390 
00391             $this->_setFieldData( $sName, $sValue );
00392         }
00393 
00394         $sOxidField = $this->_getFieldLongName( 'oxid' );
00395         $this->_sOXID = $this->$sOxidField->value;
00396 
00397     }
00398 
00404     public function getClassName()
00405     {
00406         return $this->_sClassName;
00407     }
00408 
00414     public function getCoreTableName()
00415     {
00416         return $this->_sCoreTable;
00417     }
00418 
00424     public function getId()
00425     {
00426         return $this->_sOXID;
00427     }
00428 
00436     public function setId($sOXID = null)
00437     {
00438         if ( $sOXID ) {
00439             $this->_sOXID = $sOXID;
00440         } else {
00441             $this->_sOXID = oxUtilsObject::getInstance()->generateUID();
00442         }
00443 
00444         $sIdVarName = $this->_sCoreTable . "__oxid";
00445         $this->$sIdVarName = new oxField($this->_sOXID, oxField::T_RAW);
00446 
00447         return $this->_sOXID;
00448     }
00449 
00457     public function setShopId($iShopId)
00458     {
00459         $this->_iShopId = $iShopId;
00460     }
00461 
00467     public function getShopId()
00468     {
00469         return $this->_iShopId;
00470     }
00471 
00479     public function getViewName($blForceCoreTableUsage = null)
00480     {
00481         if (!$this->_sViewTable || ($blForceCoreTableUsage !== null)) {
00482             if ( ($blForceCoreTableUsage !== null)?$blForceCoreTableUsage:$this->_blForceCoreTableUsage ) {
00483                 $iShopId = -1;
00484             } else {
00485                 $iShopId = oxConfig::getInstance()->getShopId();
00486             }
00487             $sViewName = getViewName( $this->_sCoreTable, -1, $iShopId);
00488             if ($blForceCoreTableUsage !== null) {
00489                 return $sViewName;
00490             }
00491             $this->_sViewTable = $sViewName;
00492         }
00493         return $this->_sViewTable;
00494     }
00495 
00504     public function modifyCacheKey( $sCacheKey, $blOverride = false )
00505     {
00506         if ( $blOverride ) {
00507             $this->_sCacheKey = $sCacheKey;
00508         } else {
00509             $this->_sCacheKey .= $sCacheKey;
00510         }
00511     }
00512 
00518     public function disableLazyLoading()
00519     {
00520         $this->_blUseLazyLoading = false;
00521         $this->_initDataStructure(true);
00522     }
00523 
00524 
00530     public function isDerived()
00531     {
00532 
00533         return $this->_blIsDerived;
00534     }
00535 
00543     public function setIsDerived($blVal)
00544     {
00545         $this->_blIsDerived = $blVal;
00546     }
00547 
00554     public function isMultilang()
00555     {
00556         return false;
00557     }
00558 
00568     public function load( $sOXID)
00569     {
00570         /*
00571         if( !isset($oxID)){
00572             $oEx = oxNew('oxObjectException','core');
00573             $oEx->setMessage('EXCEPTION_OBJECT_OXIDNOTSET');
00574             $oEx->setObject($this);
00575             throw $oEx;
00576         }*/
00577 
00578         //getting at least one field before lazy loading the object
00579         $this->_addField('oxid', 0);
00580         $sSelect = $this->buildSelectString( array( $this->getViewName().".oxid" => $sOXID));
00581 
00582         return $this->_isLoaded = $this->assignRecord( $sSelect );
00583     }
00584 
00590     public function isLoaded()
00591     {
00592         return $this->_isLoaded;
00593     }
00594 
00602     public function buildSelectString( $aWhere = null)
00603     {
00604         $oDB = oxDb::getDb(true);
00605         $myUtils = oxUtils::getInstance();
00606 
00607         $sGet = $this->getSelectFields();
00608         $sSelect = "select $sGet from " . $this->getViewName() . " where 1 ";
00609 
00610         if ( $aWhere) {
00611             reset($aWhere);
00612             while (list($name, $value) = each($aWhere)) {
00613                 $sSelect .=  " and " . $name.' = '.$oDB->quote($value);
00614             }
00615         }
00616 
00617         // add active shop
00618 
00619         return $sSelect;
00620     }
00621 
00629     public function assignRecord( $sSelect)
00630     {
00631         $blRet = false;
00632 
00633         $oDB = oxDb::getDb(true);
00634 
00635         $rs = $oDB->execute( $sSelect);
00636         if ($rs != false && $rs->recordCount() > 0) {
00637             $blRet = true;
00638             $this->assign( $rs->fields);
00639         }
00640 
00641         return $blRet;
00642     }
00643 
00651     public function getFieldData( $sFieldName )
00652     {
00653         $sLongFieldName = $this->_getFieldLongName( $sFieldName );
00654             return $this->$sLongFieldName->value;
00655     }
00656 
00662     public function getSelectFields()
00663     {
00664         $aSelectFields = array();
00665 
00666         $sViewName = $this->getViewName();
00667 
00668         foreach ( $this->_aFieldNames as $sKey => $sField ) {
00669             $aSelectFields[] = $sViewName . '.' . $sKey;
00670         }
00671 
00672         $sSelectFields = join( ", ", $aSelectFields );
00673         return $sSelectFields;
00674     }
00675 
00683     public function delete( $sOXID = null)
00684     {
00685         if ( !$sOXID ) {
00686             $sOXID = $this->getId();
00687 
00688             //do not allow derived deletion
00689             if ( !$this->allowDerivedDelete() ) {
00690                 return false;
00691             }
00692         }
00693 
00694         if ( !$sOXID ) {
00695             return false;
00696         }
00697 
00698 
00699         $oDB = oxDb::getDb(true);
00700         $sDelete = "delete from $this->_sCoreTable where oxid = ".$oDB->quote( $sOXID );
00701         $rs = $oDB->execute( $sDelete );
00702         if ( $blDelete = ( bool ) $oDB->affected_Rows() ) {
00703             $this->onChange(ACTION_DELETE, $sOXID);
00704         }
00705 
00706         return $blDelete;
00707     }
00708 
00709 
00715     public function save()
00716     {
00717         if ( !is_array( $this->_aFieldNames ) ) {
00718             return false;
00719         }
00720 
00721         $blRet = false;
00722 
00723         // #739A - should be executed here because of date/time formatting feature
00724         if ( $this->isAdmin() && !$this->getConfig()->getConfigParam( 'blSkipFormatConversion' ) ) {
00725             foreach ($this->_aFieldNames as $sName => $sVal) {
00726                 $sLongName = $this->_getFieldLongName($sName);
00727                 if ( isset($this->$sLongName->fldtype) && $this->$sLongName->fldtype == "datetime" ) {
00728                     oxDb::getInstance()->convertDBDateTime( $this->$sLongName, true );
00729                 } elseif ( isset($this->$sLongName->fldtype) && $this->$sLongName->fldtype == "timestamp" ) {
00730                     oxDb::getInstance()->convertDBTimestamp( $this->$sLongName, true);
00731                 } elseif ( isset($this->$sLongName->fldtype) && $this->$sLongName->fldtype == "date" ) {
00732                     oxDb::getInstance()->convertDBDate( $this->$sLongName, true);
00733                 }
00734             }
00735         }
00736         if ( $this->exists() ) {
00737             //do not allow derived update
00738             if ( !$this->allowDerivedUpdate() ) {
00739                 return false;
00740             }
00741 
00742             $blRet = $this->_update();
00743             $sAction = ACTION_UPDATE;
00744         } else {
00745             $blRet = $this->_insert();
00746             $sAction = ACTION_INSERT;
00747         }
00748 
00749         $this->onChange($sAction);
00750 
00751         if ( $blRet ) {
00752             return $this->getId();
00753         } else {
00754             return false;
00755         }
00756     }
00757 
00763     public function allowDerivedUpdate()
00764     {
00765         return !$this->isDerived();
00766     }
00767 
00773     public function allowDerivedDelete()
00774     {
00775         return !$this->isDerived();
00776     }
00777 
00785     public function exists( $sOXID = null)
00786     {
00787         if ( !$sOXID ) {
00788             $sOXID = $this->getId();
00789         }
00790         if ( !$sOXID ) {
00791             return false;
00792         }
00793 
00794         $sViewName = $this->getCoreTableName();
00795         $oDB = oxDb::getDb( true );
00796         $sSelect= "select {$this->_sExistKey} from {$sViewName} where {$this->_sExistKey} = ".$oDB->quote( $sOXID );
00797 
00798         return ( bool ) $oDB->getOne( $sSelect );
00799     }
00800 
00808     public function getSqlActiveSnippet( $blForceCoreTable = null )
00809     {
00810         $sQ = '';
00811         $sTable = $this->getViewName($blForceCoreTable);
00812 
00813         // has 'active' field ?
00814         if ( isset( $this->_aFieldNames['oxactive'] ) ) {
00815             $sQ = " $sTable.oxactive = 1 ";
00816         }
00817 
00818         // has 'activefrom'/'activeto' fields ?
00819         if ( isset( $this->_aFieldNames['oxactivefrom'] ) && isset( $this->_aFieldNames['oxactiveto'] ) ) {
00820 
00821             $sDate = date( 'Y-m-d H:i:s', oxUtilsDate::getInstance()->getTime() );
00822 
00823             $sQ = $sQ?" $sQ or ":'';
00824             $sQ = " ( $sQ ( $sTable.oxactivefrom < '$sDate' and $sTable.oxactiveto > '$sDate' ) ) ";
00825         }
00826 
00827         return $sQ;
00828     }
00829 
00838     public function validate()
00839     {
00840         $this->_aErrors = array();
00841         foreach ($this->_aFieldNames as $fName => $iVal) {
00842 
00843             $fName = $this->_getFieldLongName($fName);
00844 
00845             if ( method_exists ( $this, "validate_$fName")) {
00846                 $validatorMethod = "validate_$fName";
00847                 if ( $error = $this->$validatorMethod()) {
00848                     $this->_aErrors[$fName] = $error;
00849                 }
00850             }
00851         }
00852         return !$this->hasErrors();
00853     }
00854 
00863     public function beforeUpdate( $sOXID = null )
00864     {
00865     }
00866 
00877     public function onChange( $iAction = null, $sOXID = null)
00878     {
00879     }
00880 
00881 
00889     public function hasErrors()
00890     {
00891         return count($this->_aErrors) > 0;
00892     }
00893 
00901     public function getErrors()
00902     {
00903         return $this->_aErrors;
00904     }
00905 
00915     public function getError( $sField)
00916     {
00917         if (isset($this->_aErrors[$sField])) {
00918             return $this->_aErrors[$sField];
00919         }
00920 
00921         //T2007-10-19
00922         //return array();
00923         return null;
00924     }
00925 
00935     public function getHtmlError( $sField)
00936     {
00937         if ( $error = $this->getError($sField) ) {
00938             return $error;
00939         }
00940     }
00941 
00947     public function setInList()
00948     {
00949         $this->_blIsInList = true;
00950     }
00951 
00957     protected function _isInList()
00958     {
00959         return $this->_blIsInList;
00960     }
00961 
00970     protected function _getObjectViewName( $sTable, $sShopID = null)
00971     {
00972         if ( $this->_blForceCoreTableUsage ) {
00973             $sShopID = -1;
00974         }
00975         return getViewName( $sTable, -1, $sShopID);
00976     }
00977 
00978 
00989     protected function _getTableFields($sTable, $blReturnSimple = false)
00990     {
00991         $myUtils = oxUtils::getInstance();
00992 
00993         $sCacheKey   = $sTable . "_allfields_" . $blReturnSimple;
00994         $aMetaFields = $myUtils->fromFileCache( $sCacheKey );
00995 
00996         if ( $aMetaFields ) {
00997             return $aMetaFields;
00998         }
00999 
01000         $aMetaFields = oxDb::getInstance()->getTableDescription( $sTable );
01001 
01002         if ( !$blReturnSimple ) {
01003             $myUtils->toFileCache( $sCacheKey, $aMetaFields );
01004             return $aMetaFields;
01005         }
01006 
01007         //returning simple array
01008         $aRet = array();
01009         if (is_array($aMetaFields)) {
01010             foreach ( $aMetaFields as $oVal ) {
01011                 $aRet[strtolower( $oVal->name )] = 0;
01012             }
01013         }
01014 
01015         $myUtils->toFileCache( $sCacheKey, $aRet);
01016 
01017         return $aRet;
01018     }
01019 
01031     protected function _getAllFields($blReturnSimple = false)
01032     {
01033         if (!$this->_sCoreTable) {
01034             return array();
01035         }
01036         return $this->_getTableFields($this->_sCoreTable, $blReturnSimple);
01037     }
01038 
01047     protected function _initDataStructure($blForceFullStructure = false)
01048     {
01049         $myUtils = oxUtils::getInstance();
01050 
01051         //get field names from cache
01052         $aFieldNames = null;
01053         $sFullCacheKey = 'fieldnames_' .$this->_sCoreTable . "_" . $this->_sCacheKey;
01054         if ($this->_sCacheKey && !$this->_isDisabledFieldCache()) {
01055             $aFieldNames = $myUtils->fromFileCache($sFullCacheKey);
01056         }
01057 
01058         if (!$aFieldNames) {
01059             $aFieldNames = $this->_getNonCachedFieldNames($blForceFullStructure);
01060             if ($this->_sCacheKey && !$this->_isDisabledFieldCache()) {
01061                 $myUtils->toFileCache($sFullCacheKey, $aFieldNames);
01062             }
01063         }
01064 
01065         if ( $aFieldNames !== false ) {
01066             foreach ( $aFieldNames as $sField => $sStatus ) {
01067                 $this->_addField($sField, $sStatus);
01068             }
01069         }
01070     }
01071 
01083     protected function _getNonCachedFieldNames($blForceFullStructure = false)
01084     {
01085         //T2008-02-22
01086         //so if this method is executed on cached version we see it when profiling
01087         startProfile("!__CACHABLE__!");
01088 
01089         //case 1. (admin)
01090         if ($this->isAdmin()) {
01091             $aMetaFields = $this->_getAllFields();
01092             foreach ( $aMetaFields as $oField ) {
01093                 if ( $oField->max_length == -1 ) {
01094                     $oField->max_length = 10;      // double or float
01095                 }
01096 
01097                 if ( $oField->type == "datetime" ) {
01098                     $oField->max_length = 20;
01099                 }
01100 
01101                 $this->_addField( $oField->name, $this->_getFieldStatus($oField->name), $oField->type, $oField->max_length );
01102             }
01103             stopProfile("!__CACHABLE__!");
01104             return false;
01105         }
01106 
01107         //case 2. (just get all fields)
01108         if ( $blForceFullStructure || !$this->_blUseLazyLoading ) {
01109             $aMetaFields = $this->_getAllFields(true);
01110             /*
01111             foreach ( $aMetaFields as $sFieldName => $sVal) {
01112                 $this->_addField( $sFieldName, $this->_getFieldStatus($sFieldName));
01113             }*/
01114             stopProfile("!__CACHABLE__!");
01115             return $aMetaFields;
01116         }
01117 
01118         //case 3. (get only oxid field, so we can fetch the rest of the fields over lazy loading mechanism)
01119         stopProfile("!__CACHABLE__!");
01120         return array("oxid" => 0);
01121     }
01122 
01131     protected function _getFieldStatus( $sFieldName )
01132     {
01133         return 0;
01134     }
01135 
01146     protected function _addField($sName, $iStatus, $sType = null, $sLength = null)
01147     {
01148         //preparation
01149         $sName = strtolower( $sName );
01150 
01151         //adding field names element
01152         $this->_aFieldNames[$sName] = $iStatus;
01153 
01154         //allready set?
01155         $sLongName = $this->_getFieldLongName($sName);
01156         if ( isset($this->$sLongName) ) {
01157             return;
01158         }
01159 
01160         //defining the field
01161         $oField = false;
01162 
01163         if ( isset( $sType ) ) {
01164             $oField = new oxField();
01165             $oField->fldtype = $sType;
01166             //T2008-01-29
01167             //can't clone as the fields are objects and are not fully cloned
01168             $this->_blIsSimplyClonable = false;
01169         }
01170 
01171         if ( isset( $sLength ) ) {
01172             if ( !$oField ) {
01173                 $oField = new oxField();
01174             }
01175             $oField->fldmax_length = $sLength;
01176             $this->_blIsSimplyClonable = false;
01177         }
01178 
01179         $this->$sLongName = $oField;
01180     }
01181 
01189     protected function _getFieldLongName( $sFieldName )
01190     {
01191         //trying to avoid strpos call as often as possible
01192         if ( $sFieldName[2] == $this->_sCoreTable[2] && strpos( $sFieldName, $this->_sCoreTable . "__" ) === 0 ) {
01193             return $sFieldName;
01194         }
01195 
01196         return $this->_sCoreTable . "__" . strtolower( $sFieldName );
01197     }
01198 
01208     protected function _setFieldData( $sFieldName, $sValue, $iDataType = oxField::T_TEXT)
01209     {
01210 
01211         $sLongFieldName = $this->_getFieldLongName( $sFieldName);
01212         //$sLongFieldName = $this->_sCoreTable . "__" . strtolower($sFieldName);
01213 
01214         //T2008-03-14
01215         //doing this because in lazy loaded lists on first load it is harmful to have initilised fields but not yet set
01216         //situation: only first article is loaded fully for "select oxid from oxarticles"
01217         /*
01218         if ($this->_blUseLazyLoading && !isset($this->$sLongFieldName))
01219             return;*/
01220 
01221         //in non lazy loading case we just add a field and do not care about it more
01222         if (!$this->_blUseLazyLoading && !isset($this->$sLongFieldName)) {
01223             $aFields = $this->_getAllFields(true);
01224             if ( isset( $aFields[strtolower($sFieldName)] ) ) {
01225                 $this->_addField($sFieldName, $this->_getFieldStatus($sFieldName));
01226             }
01227         }
01228         // if we have a double field we replace "," with "." in case somebody enters it in european format
01229         if (isset($this->$sLongFieldName) && isset($this->$sLongFieldName->fldtype) && $this->$sLongFieldName->fldtype == "double") {
01230             $sValue = str_replace( ",", ".", $sValue );
01231         }
01232 
01233         // isset is REQUIRED here not to use getter
01234         if (isset($this->$sLongFieldName) && is_object($this->$sLongFieldName)) {
01235             $this->$sLongFieldName->setValue($sValue, $iDataType);
01236         } else {
01237             $this->$sLongFieldName = new oxField($sValue, $iDataType);
01238         }
01239 
01240     }
01241 
01249     protected function _canFieldBeNull( $sFieldName )
01250     {
01251         $aMetaData = $this->_getAllFields();
01252         foreach ( $aMetaData as $oMetaInfo ) {
01253             if ( strcasecmp( $oMetaInfo->name, $sFieldName ) == 0 ) {
01254                 return !$oMetaInfo->not_null;
01255             }
01256         }
01257         return false;
01258     }
01259 
01268     protected function _getUpdateFieldValue( $sFieldName, $oField )
01269     {
01270         $mValue = null;
01271         if ( $oField instanceof oxField ) {
01272             $mValue = $oField->getRawValue();
01273         } elseif ( isset( $oField->value ) ) {
01274             $mValue = $oField->value;
01275         }
01276         // Sarunas. check if this field value is null AND it can be null according to table description
01277         if ( ( null === $mValue ) && $this->_canFieldBeNull( $sFieldName ) ) {
01278             return 'null';
01279         }
01280         return oxDb::getDb()->quote( $mValue );
01281     }
01282 
01291     protected function _getUpdateFields( $blUseSkipSaveFields = true )
01292     {
01293         $sSql = '';
01294         $blSep  = false;
01295 
01296         foreach (array_keys($this->_aFieldNames) as $sKey) {
01297             $sLongName = $this->_getFieldLongName($sKey);
01298             $oField = $this->$sLongName;
01299 
01300 
01301             if ( !$blUseSkipSaveFields || ($blUseSkipSaveFields && !in_array(strtolower($sKey), $this->_aSkipSaveFields)) ) {
01302                 $sSql .= (( $blSep) ? ',':'' ).$sKey." = ".$this->_getUpdateFieldValue($sKey, $oField);
01303                 $blSep = true;
01304             }
01305         }
01306 
01307         return $sSql;
01308     }
01309 
01319     protected function _update()
01320     {
01321         //do not allow derived item update
01322         if ( !$this->allowDerivedUpdate() ) {
01323             return false;
01324         }
01325 
01326 
01327         if ( !$this->getId() ) {
01328             $oEx = oxNew( 'oxObjectException' );
01329             $oEx->setMessage( 'EXCEPTION_OBJECT_OXIDNOTSET' );
01330             $oEx->setObject($this);
01331             throw $oEx;
01332         }
01333 
01334         $sIDKey = oxUtils::getInstance()->getArrFldName( $this->_sCoreTable.".oxid");
01335         $this->$sIDKey = new oxField($this->getId(), oxField::T_RAW);
01336         $oDb = oxDB::getDb();
01337 
01338         $sUpdate= "update {$this->_sCoreTable} set ".$this->_getUpdateFields()
01339                  ." where {$this->_sCoreTable}.oxid = ".$oDb->quote( $this->getId() );
01340 
01341         //trigger event
01342         $this->beforeUpdate();
01343 
01344         $blRet = (bool) $oDb->execute( $sUpdate);
01345         $this->_rebuildCache();
01346 
01347         return $blRet;
01348     }
01349 
01357     protected function _insert()
01358     {
01359 
01360         $oDB      = oxDb::getDb(true);
01361         $myConfig = $this->getConfig();
01362         $myUtils  = oxUtils::getInstance();
01363 
01364         // let's get a new ID
01365         if ( !$this->getId()) {
01366             $this->setId();
01367         }
01368 
01369         $sIDKey = $myUtils->getArrFldName( $this->_sCoreTable.".oxid");
01370         $this->$sIDKey = new oxField($this->getId(), oxField::T_RAW);
01371         $sInsert= "Insert into {$this->_sCoreTable} set ";
01372 
01373         //setting oxshopid
01374         $sShopField = $myUtils->getArrFldName($this->_sCoreTable.".oxshopid");
01375         if (isset($this->$sShopField) && !$this->$sShopField->value)
01376             $this->$sShopField = new oxField($myConfig->getShopId(), oxField::T_RAW);
01377 
01378         $sInsert .= $this->_getUpdateFields( false );
01379         $blRet = (bool) $oDB->execute( $sInsert);
01380 
01381         $this->_rebuildCache();
01382 
01383         return $blRet;
01384 
01385     }
01386 
01392     protected function _rebuildCache()
01393     {
01394         if ( !$this->_blIsNewCache) {
01395             oxUtils::getInstance()->rebuildCache();
01396             $this->_blIsNewCache = true;
01397         }
01398     }
01399 
01409     protected function _setRecordNumber( $sMaxField, $aWhere = null, $iMaxTryCnt = 5 )
01410     {
01411         // filtering
01412         $sWhere = "";
01413         if ( is_array( $aWhere ) && count( $aWhere ) > 0) {
01414             $sWhere = implode(" and ", $aWhere).' and ';
01415         }
01416         $oDb = oxDb::getDb(true);
01417 
01418         // SQL to set record number
01419         $sUpdate = "update {$this->getViewName()} as t1, (select (max($sMaxField)+1) as t2max from {$this->getViewName()} where $sWhere 1) as t2 set t1.$sMaxField=t2.t2max where t1.oxid = ".$oDb->quote( $this->getId() );
01420 
01421         // SQL to check record number dublicates
01422         //this should not happen normally but we prefer to take extra care in this case due to parallel script execution etc.
01423         $sMaxSelect = "select $sMaxField from ".$this->getViewName()." where oxid=".$oDb->quote( $this->getId() );
01424         $sCheck = "select count(oxid) from ".$this->getViewName()." where $sMaxField = ($sMaxSelect) and $sWhere 1 ";
01425 
01426         do {
01427             if ( $oDb->execute( $sUpdate ) === false ) {
01428                 return false;
01429             }
01430 
01431             $iChkCnt = $oDb->getOne( $sCheck );
01432         } while ( ( $iChkCnt > 1 ) && $iMaxTryCnt-- );
01433 
01434         $sFieldName = $this->getViewName().'__'.$sMaxField;
01435         $this->$sFieldName = new oxField( $oDb->getOne( $sMaxSelect ), oxField::T_RAW);//int value
01436 
01437         return ( $iChkCnt == 1 );
01438     }
01439 
01446     protected function _isDisabledFieldCache()
01447     {
01448         $sClass = get_class($this);
01449         if (isset(self::$_blDisableFieldCaching[$sClass]) && self::$_blDisableFieldCaching[$sClass]) {
01450             return true;
01451         }
01452 
01453         return false;
01454     }
01455 
01461     public function isOx()
01462     {
01463         $sOxId = $this->getId();
01464         if ( $sOxId[0] == 'o' && $sOxId[1] == 'x' ) {
01465             return true;
01466         }
01467         return false;
01468     }
01469 
01475     public function isReadOnly()
01476     {
01477         return $this->_blReadOnly;
01478     }
01479 
01487     public function setReadOnly( $blReadOnly )
01488     {
01489         $this->_blReadOnly = $blReadOnly;
01490     }
01491 
01497     public function getFieldNames()
01498     {
01499         return array_keys( $this->_aFieldNames );
01500     }
01501 }