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 
00041     protected $_sClassName = 'oxbase';
00042 
00048     protected $_sCoreTable = null;
00049 
00054     protected $_sViewTable  = null;
00055 
00056 
00062     protected $_aFieldNames = array('oxid' => 0);
00063 
00069     protected $_sCacheKey = null;
00070 
00076     protected $_blUseLazyLoading = false;
00077 
00083     protected $_aSkipSaveFields = array('oxtimestamp');
00084 
00090     protected $_blUseSkipSaveFields = true;
00091 
00096     protected $_sExistKey = 'oxid';
00097 
00104     protected $_blIsDerived = null;
00105 
00115     protected static $_blDisableFieldCaching = array();
00116 
00122     protected $_blIsSeoObject = false;
00123 
00129     protected $_blReadOnly = false;
00130 
00136     protected $_blIsInList = false;
00137 
00143     protected $_isLoaded = false;
00144 
00150     protected $_aInnerLazyCache = null;
00151 
00157     protected $_blEmployMultilanguage = false;
00158 
00159 
00165     public function getUseSkipSaveFields()
00166     {
00167         return $this->_blUseSkipSaveFields;
00168     }
00169 
00177     public function setUseSkipSaveFields( $blUseSkipSaveFields )
00178     {
00179         $this->_blUseSkipSaveFields = $blUseSkipSaveFields;
00180     }
00181 
00185     public function __construct()
00186     {
00187         // set active shop
00188         $myConfig = $this->getConfig();
00189         $this->_sCacheKey = $this->getViewName();
00190 
00191 
00192         if ( $this->_blUseLazyLoading ) {
00193             $this->_sCacheKey .= $myConfig->getActiveView()->getClassName();
00194         } else {
00195             $this->_sCacheKey .= 'allviews';
00196         }
00197 
00198         //do not cache for admin?
00199         if ( $this->isAdmin() ) {
00200             $this->_sCacheKey = null;
00201         }
00202 
00203         $this->setShopId( $myConfig->getShopId() );
00204     }
00205 
00214     public function __set( $sName, $sValue )
00215     {
00216         $this->$sName = $sValue;
00217         if ( $this->_blUseLazyLoading && strpos( $sName, $this->_sCoreTable . '__' ) === 0 ) {
00218             $sFieldName = str_replace( $this->_sCoreTable . "__", '', $sName );
00219             if ( $sFieldName != 'oxnid' && ( !isset( $this->_aFieldNames[$sFieldName] ) || !$this->_aFieldNames[$sFieldName] ) ) {
00220                 $aAllFields = $this->_getAllFields(true);
00221                 if ( isset( $aAllFields[strtolower($sFieldName)] ) ) {
00222                     $iFieldStatus = $this->_getFieldStatus( $sFieldName );
00223                     $this->_addField( $sFieldName, $iFieldStatus );
00224                 }
00225             }
00226         }
00227     }
00228 
00236     public function __get( $sName )
00237     {
00238         switch ( $sName ) {
00239             case 'blIsDerived':
00240                 return $this->isDerived();
00241                 break;
00242             case 'sOXID':
00243                 return $this->getId();
00244                 break;
00245             case 'blReadOnly':
00246                 return $this->isReadOnly();
00247                 break;
00248         }
00249 
00250         // implementing lazy loading fields
00251         // This part of the code is slow and normally is called before field cache is built.
00252         // Make sure it is not called after first page is loaded and cache data is fully built.
00253         if ( $this->_blUseLazyLoading && stripos( $sName, $this->_sCoreTable . "__" ) === 0 ) {
00254 
00255             if ( $this->getId() ) {
00256 
00257                 //lazy load it
00258                 $sFieldName      = str_replace( $this->_sCoreTable . '__', '', $sName );
00259                 $sCacheFieldName = strtoupper( $sFieldName );
00260 
00261                 $iFieldStatus = $this->_getFieldStatus( $sFieldName );
00262                 $sViewName    = $this->getViewName();
00263                 $sId = $this->getId();
00264 
00265                 try {
00266                     if ( $this->_aInnerLazyCache === null ) {
00267 
00268                         $oDb = oxDb::getDb( oxDb::FETCH_MODE_ASSOC );
00269                         $sQ = 'SELECT * FROM ' . $sViewName . ' WHERE `oxid` = ' . $oDb->quote( $sId );
00270                         $rs = $oDb->select( $sQ );
00271                         if ( $rs && $rs->RecordCount() ) {
00272                             $this->_aInnerLazyCache = array_change_key_case( $rs->fields, CASE_UPPER );
00273                             if ( array_key_exists( $sCacheFieldName, $this->_aInnerLazyCache ) ) {
00274                                 $sFieldValue = $this->_aInnerLazyCache[$sCacheFieldName];
00275                             } else {
00276                                 return null;
00277                             }
00278                         } else {
00279                             return null;
00280                         }
00281                     } elseif ( array_key_exists( $sCacheFieldName, $this->_aInnerLazyCache ) ) {
00282                         $sFieldValue = $this->_aInnerLazyCache[$sCacheFieldName];
00283                     } else {
00284                         return null;
00285                     }
00286 
00287                     $this->_addField( $sFieldName, $iFieldStatus );
00288                     $this->_setFieldData( $sFieldName, $sFieldValue );
00289 
00290                     //save names to cache for next loading
00291                     if ($this->_sCacheKey) {
00292                         $myUtils = oxRegistry::getUtils();
00293                         $sCacheKey = 'fieldnames_' . $this->_sCoreTable . '_' . $this->_sCacheKey;
00294                         $aFieldNames = $myUtils->fromFileCache( $sCacheKey );
00295                         $aFieldNames[$sFieldName] = $iFieldStatus;
00296                         $myUtils->toFileCache( $sCacheKey, $aFieldNames );
00297                     }
00298                 } catch ( Exception $e ) {
00299                     return null;
00300                 }
00301 
00302                 //do not use field cache for this page
00303                 //as if we use it for lists then objects are loaded empty instead of lazy loading.
00304                 self::$_blDisableFieldCaching[get_class( $this )] = true;
00305             }
00306 
00307             oxUtilsObject::getInstance()->resetInstanceCache(get_class($this));
00308         }
00309 
00310         //returns stdClass implementing __toString() method due to uknown scenario where this var should be used.
00311         if (!isset( $this->$sName ) ) {
00312             $this->$sName = null;
00313         }
00314 
00315         return $this->$sName;
00316     }
00317 
00325     public function __isset($mVar)
00326     {
00327         return isset($this->$mVar);
00328     }
00329 
00335     public function __clone()
00336     {
00337         if (!$this->_blIsSimplyClonable) {
00338             foreach ( $this->_aFieldNames as $sField => $sVal ) {
00339                 $sLongName = $this->_getFieldLongName( $sField );
00340                 if ( is_object($this->$sLongName)) {
00341                     $this->$sLongName = clone $this->$sLongName;
00342                 }
00343             }
00344         }
00345     }
00346 
00354     public function oxClone( $oObject )
00355     {
00356         $aClasVars = get_object_vars( $oObject );
00357         while (list($name, $value) = each( $aClasVars )) {
00358             if ( is_object( $oObject->$name ) ) {
00359                 $this->$name = clone $oObject->$name;
00360             } else {
00361                 $this->$name = $oObject->$name;
00362             }
00363         }
00364     }
00365 
00374     public function init( $sTableName = null, $blForceAllFields = false )
00375     {
00376         if ( $sTableName ) {
00377             $this->_sCoreTable = $sTableName;
00378         }
00379 
00380         // reset view table
00381         $this->_sViewTable = false;
00382 
00383         if ( count( $this->_aFieldNames ) <= 1 ) {
00384             $this->_initDataStructure( $blForceAllFields );
00385         }
00386     }
00387 
00395     public function assign( $dbRecord )
00396     {
00397         if ( !is_array( $dbRecord ) ) {
00398             return;
00399         }
00400 
00401 
00402         reset($dbRecord );
00403         while ( list( $sName, $sValue ) = each( $dbRecord ) ) {
00404 
00405             // patch for IIS
00406             //TODO: test it on IIS do we still need it
00407             //if( is_array($value) && count( $value) == 1)
00408             //    $value = current( $value);
00409 
00410             $this->_setFieldData( $sName, $sValue );
00411         }
00412 
00413         $sOxidField = $this->_getFieldLongName( 'oxid' );
00414         $this->_sOXID = $this->$sOxidField->value;
00415 
00416     }
00417 
00423     public function getClassName()
00424     {
00425         return $this->_sClassName;
00426     }
00427 
00433     public function getCoreTableName()
00434     {
00435         return $this->_sCoreTable;
00436     }
00437 
00443     public function getId()
00444     {
00445         return $this->_sOXID;
00446     }
00447 
00455     public function setId( $sOXID = null )
00456     {
00457         if ( $sOXID ) {
00458             $this->_sOXID = $sOXID;
00459         } else {
00460             $this->_sOXID = oxUtilsObject::getInstance()->generateUID();
00461         }
00462 
00463         $sIdVarName = $this->_sCoreTable . '__oxid';
00464         $this->$sIdVarName = new oxField($this->_sOXID, oxField::T_RAW);
00465 
00466         return $this->_sOXID;
00467     }
00468 
00476     public function setShopId( $iShopId )
00477     {
00478         $this->_iShopId = $iShopId;
00479     }
00480 
00486     public function getShopId()
00487     {
00488         return $this->_iShopId;
00489     }
00490 
00498     public function getViewName( $blForceCoreTableUsage = null )
00499     {
00500         if (!$this->_sViewTable || ( $blForceCoreTableUsage !== null )) {
00501             if ( $blForceCoreTableUsage === true ) {
00502                 return $this->_sCoreTable;
00503             }
00504 
00505 
00506             if ( ( $blForceCoreTableUsage !== null ) && $blForceCoreTableUsage ) {
00507                 $iShopId = -1;
00508             } else {
00509                 $iShopId = oxRegistry::getConfig()->getShopId();
00510             }
00511 
00512             $sViewName = getViewName( $this->_sCoreTable, $this->_blEmployMultilanguage == false ? -1 : $this->getLanguage(), $iShopId );
00513             if ( $blForceCoreTableUsage !== null ) {
00514                 return $sViewName;
00515             }
00516             $this->_sViewTable = $sViewName;
00517         }
00518         return $this->_sViewTable;
00519     }
00520 
00529     public function modifyCacheKey( $sCacheKey, $blOverride = false )
00530     {
00531         if ( $blOverride ) {
00532             $this->_sCacheKey = $sCacheKey;
00533         } else {
00534             $this->_sCacheKey .= $sCacheKey;
00535         }
00536     }
00537 
00543     public function disableLazyLoading()
00544     {
00545         $this->_blUseLazyLoading = false;
00546         $this->_initDataStructure(true);
00547     }
00548 
00549 
00555     public function isDerived()
00556     {
00557 
00558         return $this->_blIsDerived;
00559     }
00560 
00568     public function setIsDerived( $blVal )
00569     {
00570         $this->_blIsDerived = $blVal;
00571     }
00572 
00579     public function isMultilang()
00580     {
00581         return false;
00582     }
00583 
00593     public function load( $sOXID )
00594     {
00595         $blExistingOldForceCoreTable = $this->_blForceCoreTableUsage;
00596 
00597         $this->_blForceCoreTableUsage = true;
00598 
00599         //getting at least one field before lazy loading the object
00600         $this->_addField( 'oxid', 0 );
00601         $sSelect = $this->buildSelectString( array( $this->getViewName() . '.oxid' => $sOXID) );
00602         $this->_isLoaded = $this->assignRecord( $sSelect );
00603 
00604         $this->_blForceCoreTableUsage = $blExistingOldForceCoreTable;
00605 
00606         return $this->_isLoaded;
00607     }
00608 
00614     public function isLoaded()
00615     {
00616         return $this->_isLoaded;
00617     }
00618 
00626     public function buildSelectString( $aWhere = null)
00627     {
00628         $oDB = oxDb::getDb();
00629 
00630         $sGet = $this->getSelectFields();
00631         $sSelect = "select $sGet from " . $this->getViewName() . ' where 1 ';
00632 
00633         if ( $aWhere) {
00634             reset($aWhere);
00635             while (list($name, $value) = each($aWhere)) {
00636                 $sSelect .=  ' and ' . $name . ' = '.$oDB->quote($value);
00637             }
00638         }
00639 
00640         // add active shop
00641 
00642         //echo $sSelect;
00643 
00644         return $sSelect;
00645     }
00646 
00654     public function assignRecord( $sSelect )
00655     {
00656         $blRet = false;
00657 
00658         $rs = oxDb::getDb( oxDb::FETCH_MODE_ASSOC )->select( $sSelect );
00659 
00660         if ($rs != false && $rs->recordCount() > 0) {
00661             $blRet = true;
00662             $this->assign( $rs->fields);
00663         }
00664 
00665         return $blRet;
00666     }
00667 
00675     public function getFieldData( $sFieldName )
00676     {
00677         $sLongFieldName = $this->_getFieldLongName( $sFieldName );
00678             return $this->$sLongFieldName->value;
00679     }
00680 
00688     public function getSelectFields( $blForceCoreTableUsage = null )
00689     {
00690         $aSelectFields = array();
00691 
00692         $sViewName = $this->getViewName( $blForceCoreTableUsage );
00693 
00694         foreach ( $this->_aFieldNames as $sKey => $sField ) {
00695             if ( $sViewName ) {
00696                 $aSelectFields[] = "`$sViewName`.`$sKey`";
00697             } else {
00698                 $aSelectFields[] = ".`$sKey`";
00699             }
00700 
00701         }
00702 
00703         $sSelectFields = join( ', ', $aSelectFields );
00704         return $sSelectFields;
00705     }
00706 
00714     public function delete( $sOXID = null)
00715     {
00716         if ( !$sOXID ) {
00717             $sOXID = $this->getId();
00718 
00719             //do not allow derived deletion
00720             if ( !$this->allowDerivedDelete() ) {
00721                 return false;
00722             }
00723         }
00724 
00725         if ( !$sOXID ) {
00726             return false;
00727         }
00728 
00729 
00730         $oDB = oxDb::getDb( oxDb::FETCH_MODE_ASSOC );
00731         $sDelete = "delete from $this->_sCoreTable where oxid = " . $oDB->quote( $sOXID );
00732         $oDB->execute( $sDelete );
00733         if ( $blDelete = ( bool ) $oDB->affected_Rows() ) {
00734             $this->onChange( ACTION_DELETE, $sOXID );
00735         }
00736 
00737         return $blDelete;
00738     }
00739 
00740 
00746     public function save()
00747     {
00748         if ( !is_array( $this->_aFieldNames ) ) {
00749             return false;
00750         }
00751 
00752         // #739A - should be executed here because of date/time formatting feature
00753         if ( $this->isAdmin() && !$this->getConfig()->getConfigParam( 'blSkipFormatConversion' ) ) {
00754             foreach ($this->_aFieldNames as $sName => $sVal) {
00755                 $sLongName = $this->_getFieldLongName($sName);
00756                 if ( isset($this->$sLongName->fldtype) && $this->$sLongName->fldtype == 'datetime' ) {
00757                     oxRegistry::get('oxUtilsDate')->convertDBDateTime( $this->$sLongName, true );
00758                 } elseif ( isset($this->$sLongName->fldtype) && $this->$sLongName->fldtype == 'timestamp' ) {
00759                     oxRegistry::get('oxUtilsDate')->convertDBTimestamp( $this->$sLongName, true );
00760                 } elseif ( isset($this->$sLongName->fldtype) && $this->$sLongName->fldtype == 'date' ) {
00761                     oxRegistry::get('oxUtilsDate')->convertDBDate( $this->$sLongName, true );
00762                 }
00763             }
00764         }
00765         if ( $this->exists() ) {
00766             //do not allow derived update
00767             if ( !$this->allowDerivedUpdate() ) {
00768                 return false;
00769             }
00770 
00771             $blRet = $this->_update();
00772             $sAction = ACTION_UPDATE;
00773         } else {
00774             $blRet = $this->_insert();
00775             $sAction = ACTION_INSERT;
00776         }
00777 
00778         $this->onChange($sAction);
00779 
00780         if ( $blRet ) {
00781             return $this->getId();
00782         } else {
00783             return false;
00784         }
00785     }
00786 
00792     public function allowDerivedUpdate()
00793     {
00794         return !$this->isDerived();
00795     }
00796 
00802     public function allowDerivedDelete()
00803     {
00804         return !$this->isDerived();
00805     }
00806 
00814     public function exists( $sOXID = null)
00815     {
00816         if ( !$sOXID ) {
00817             $sOXID = $this->getId();
00818         }
00819         if ( !$sOXID ) {
00820             return false;
00821         }
00822 
00823         $sViewName = $this->getCoreTableName();
00824         $oDb = oxDb::getDb( oxDb::FETCH_MODE_ASSOC );
00825         $sSelect= "select {$this->_sExistKey} from {$sViewName} where {$this->_sExistKey} = " . $oDb->quote( $sOXID );
00826 
00827         return ( bool ) $oDb->getOne( $sSelect, false, false );
00828     }
00829 
00837     public function getSqlActiveSnippet( $blForceCoreTable = null )
00838     {
00839         $sQ = '';
00840         $sTable = $this->getViewName($blForceCoreTable);
00841 
00842         // has 'active' field ?
00843         if ( isset( $this->_aFieldNames['oxactive'] ) ) {
00844             $sQ = " $sTable.oxactive = 1 ";
00845         }
00846 
00847         // has 'activefrom'/'activeto' fields ?
00848         if ( isset( $this->_aFieldNames['oxactivefrom'] ) && isset( $this->_aFieldNames['oxactiveto'] ) ) {
00849 
00850             $sDate = date( 'Y-m-d H:i:s', oxRegistry::get('oxUtilsDate')->getTime() );
00851 
00852             $sQ = $sQ ? " $sQ or " : '';
00853             $sQ = " ( $sQ ( $sTable.oxactivefrom < '$sDate' and $sTable.oxactiveto > '$sDate' ) ) ";
00854         }
00855 
00856         return $sQ;
00857     }
00858 
00867     public function beforeUpdate( $sOXID = null )
00868     {
00869     }
00870 
00881     public function onChange( $iAction = null, $sOXID = null )
00882     {
00883     }
00884 
00885 
00891     public function setInList()
00892     {
00893         $this->_blIsInList = true;
00894     }
00895 
00901     protected function _isInList()
00902     {
00903         return $this->_blIsInList;
00904     }
00905 
00914     protected function _getObjectViewName( $sTable, $sShopID = null )
00915     {
00916         return getViewName( $sTable, -1, $sShopID);
00917     }
00918 
00919 
00930     protected function _getTableFields($sTable, $blReturnSimple = false )
00931     {
00932         $myUtils = oxRegistry::getUtils();
00933 
00934         $sCacheKey   = $sTable . '_allfields_' . $blReturnSimple;
00935         $aMetaFields = $myUtils->fromFileCache( $sCacheKey );
00936 
00937         if ( $aMetaFields ) {
00938             return $aMetaFields;
00939         }
00940 
00941         $aMetaFields = oxDb::getInstance()->getTableDescription( $sTable );
00942 
00943         if ( !$blReturnSimple ) {
00944             $myUtils->toFileCache( $sCacheKey, $aMetaFields );
00945             return $aMetaFields;
00946         }
00947 
00948         //returning simple array
00949         $aRet = array();
00950         if (is_array($aMetaFields)) {
00951             foreach ( $aMetaFields as $oVal ) {
00952                 $aRet[strtolower( $oVal->name )] = 0;
00953             }
00954         }
00955 
00956         $myUtils->toFileCache( $sCacheKey, $aRet);
00957 
00958         return $aRet;
00959     }
00960 
00972     protected function _getAllFields($blReturnSimple = false )
00973     {
00974         if (!$this->_sCoreTable) {
00975             return array();
00976         }
00977         return $this->_getTableFields($this->_sCoreTable, $blReturnSimple);
00978     }
00979 
00988     protected function _initDataStructure($blForceFullStructure = false )
00989     {
00990         $myUtils = oxRegistry::getUtils();
00991 
00992         //get field names from cache
00993         $aFieldNames = null;
00994         $sFullCacheKey = 'fieldnames_' . $this->_sCoreTable . '_' . $this->_sCacheKey;
00995         if ($this->_sCacheKey && !$this->_isDisabledFieldCache()) {
00996             $aFieldNames = $myUtils->fromFileCache( $sFullCacheKey );
00997         }
00998 
00999         if (!$aFieldNames) {
01000             $aFieldNames = $this->_getNonCachedFieldNames( $blForceFullStructure );
01001             if ($this->_sCacheKey && !$this->_isDisabledFieldCache()) {
01002                 $myUtils->toFileCache( $sFullCacheKey, $aFieldNames );
01003             }
01004         }
01005 
01006         if ( $aFieldNames !== false ) {
01007             foreach ( $aFieldNames as $sField => $sStatus ) {
01008                 $this->_addField( $sField, $sStatus );
01009             }
01010         }
01011     }
01012 
01024     protected function _getNonCachedFieldNames( $blForceFullStructure = false )
01025     {
01026         //T2008-02-22
01027         //so if this method is executed on cached version we see it when profiling
01028         startProfile('!__CACHABLE__!');
01029 
01030         //case 1. (admin)
01031         if ($this->isAdmin()) {
01032             $aMetaFields = $this->_getAllFields();
01033             foreach ( $aMetaFields as $oField ) {
01034                 if ( $oField->max_length == -1 ) {
01035                     $oField->max_length = 10;      // double or float
01036                 }
01037 
01038                 if ( $oField->type == 'datetime' ) {
01039                     $oField->max_length = 20;
01040                 }
01041 
01042                 $this->_addField( $oField->name, $this->_getFieldStatus($oField->name), $oField->type, $oField->max_length );
01043             }
01044             stopProfile('!__CACHABLE__!');
01045             return false;
01046         }
01047 
01048         //case 2. (just get all fields)
01049         if ( $blForceFullStructure || !$this->_blUseLazyLoading ) {
01050             $aMetaFields = $this->_getAllFields(true);
01051             /*
01052             foreach ( $aMetaFields as $sFieldName => $sVal) {
01053                 $this->_addField( $sFieldName, $this->_getFieldStatus($sFieldName));
01054             }*/
01055             stopProfile('!__CACHABLE__!');
01056             return $aMetaFields;
01057         }
01058 
01059         //case 3. (get only oxid field, so we can fetch the rest of the fields over lazy loading mechanism)
01060         stopProfile('!__CACHABLE__!');
01061         return array('oxid' => 0);
01062     }
01063 
01072     protected function _getFieldStatus( $sFieldName )
01073     {
01074         return 0;
01075     }
01076 
01087     protected function _addField($sName, $iStatus, $sType = null, $sLength = null )
01088     {
01089         //preparation
01090         $sName = strtolower( $sName );
01091 
01092         //adding field names element
01093         $this->_aFieldNames[$sName] = $iStatus;
01094 
01095         //already set?
01096         $sLongName = $this->_getFieldLongName( $sName );
01097         if ( isset($this->$sLongName) ) {
01098             return;
01099         }
01100 
01101         //defining the field
01102         $oField = false;
01103 
01104         if ( isset( $sType ) ) {
01105             $oField = new oxField();
01106             $oField->fldtype = $sType;
01107             //T2008-01-29
01108             //can't clone as the fields are objects and are not fully cloned
01109             $this->_blIsSimplyClonable = false;
01110         }
01111 
01112         if ( isset( $sLength ) ) {
01113             if ( !$oField ) {
01114                 $oField = new oxField();
01115             }
01116             $oField->fldmax_length = $sLength;
01117             $this->_blIsSimplyClonable = false;
01118         }
01119 
01120         $this->$sLongName = $oField;
01121     }
01122 
01130     protected function _getFieldLongName( $sFieldName )
01131     {
01132         //trying to avoid strpos call as often as possible
01133         if ( $sFieldName[2] == $this->_sCoreTable[2] && strpos( $sFieldName, $this->_sCoreTable . '__' ) === 0 ) {
01134             return $sFieldName;
01135         }
01136 
01137         return $this->_sCoreTable . '__' . strtolower( $sFieldName );
01138     }
01139 
01149     protected function _setFieldData( $sFieldName, $sValue, $iDataType = oxField::T_TEXT )
01150     {
01151 
01152         $sLongFieldName = $this->_getFieldLongName( $sFieldName);
01153         //$sLongFieldName = $this->_sCoreTable . "__" . strtolower($sFieldName);
01154 
01155         //T2008-03-14
01156         //doing this because in lazy loaded lists on first load it is harmful to have initialised fields but not yet set
01157         //situation: only first article is loaded fully for "select oxid from oxarticles"
01158         /*
01159         if ($this->_blUseLazyLoading && !isset($this->$sLongFieldName))
01160             return;*/
01161 
01162         //in non lazy loading case we just add a field and do not care about it more
01163         if (!$this->_blUseLazyLoading && !isset( $this->$sLongFieldName )) {
01164             $aFields = $this->_getAllFields(true);
01165             if ( isset( $aFields[strtolower( $sFieldName )] ) ) {
01166                 $this->_addField( $sFieldName, $this->_getFieldStatus( $sFieldName ) );
01167             }
01168         }
01169         // if we have a double field we replace "," with "." in case somebody enters it in european format
01170         if (isset($this->$sLongFieldName) && isset( $this->$sLongFieldName->fldtype ) && $this->$sLongFieldName->fldtype == 'double') {
01171             $sValue = str_replace( ',', '.', $sValue );
01172         }
01173 
01174         // isset is REQUIRED here not to use getter
01175         if ( isset( $this->$sLongFieldName ) && is_object( $this->$sLongFieldName ) ) {
01176             $this->$sLongFieldName->setValue( $sValue, $iDataType );
01177         } else {
01178             $this->$sLongFieldName = new oxField( $sValue, $iDataType );
01179         }
01180 
01181     }
01182 
01190     protected function _canFieldBeNull( $sFieldName )
01191     {
01192         $aMetaData = $this->_getAllFields();
01193         foreach ( $aMetaData as $oMetaInfo ) {
01194             if ( strcasecmp( $oMetaInfo->name, $sFieldName ) == 0 ) {
01195                 return !$oMetaInfo->not_null;
01196             }
01197         }
01198         return false;
01199     }
01200 
01208     protected function _getFieldDefaultValue( $sFieldName )
01209     {
01210         $aMetaData = $this->_getAllFields();
01211         foreach ( $aMetaData as $oMetaInfo ) {
01212             if ( strcasecmp( $oMetaInfo->name, $sFieldName ) == 0 ) {
01213                 return $oMetaInfo->default_value;
01214             }
01215         }
01216         return false;
01217     }
01218 
01227     protected function _getUpdateFieldValue( $sFieldName, $oField )
01228     {
01229         $mValue = null;
01230         if ( $oField instanceof oxField ) {
01231             $mValue = $oField->getRawValue();
01232         } elseif ( isset( $oField->value ) ) {
01233             $mValue = $oField->value;
01234         }
01235 
01236         $oDb = oxDb::getDb();
01237         //Check if this field value is null AND it can be null according if not returning default value
01238         if ( ( null === $mValue ) ) {
01239             if ( $this->_canFieldBeNull( $sFieldName ) ) {
01240                 return 'null';
01241             } elseif ( $mValue = $this->_getFieldDefaultValue( $sFieldName ) ) {
01242                 return $oDb->quote( $mValue );
01243             }
01244         }
01245 
01246         return $oDb->quote( $mValue );
01247     }
01248 
01257     protected function _getUpdateFields( $blUseSkipSaveFields = true )
01258     {
01259         $sSql = '';
01260         $blSep  = false;
01261 
01262         foreach ( array_keys( $this->_aFieldNames ) as $sKey ) {
01263             $sLongName = $this->_getFieldLongName( $sKey );
01264             $oField = $this->$sLongName;
01265 
01266 
01267             if ( !$blUseSkipSaveFields || ( $blUseSkipSaveFields && !in_array( strtolower( $sKey ), $this->_aSkipSaveFields ) ) ) {
01268                 $sSql .= (( $blSep) ? ',' : '' ) . $sKey . ' = ' . $this->_getUpdateFieldValue( $sKey, $oField );
01269                 $blSep = true;
01270             }
01271         }
01272 
01273         return $sSql;
01274     }
01275 
01285     protected function _update()
01286     {
01287         //do not allow derived item update
01288         if ( !$this->allowDerivedUpdate() ) {
01289             return false;
01290         }
01291 
01292 
01293         if ( !$this->getId() ) {
01297             $oEx = oxNew( 'oxObjectException' );
01298             $oEx->setMessage( 'EXCEPTION_OBJECT_OXIDNOTSET' );
01299             $oEx->setObject($this);
01300             throw $oEx;
01301         }
01302 
01303         $sIDKey = oxRegistry::getUtils()->getArrFldName( $this->_sCoreTable . '.oxid' );
01304         $this->$sIDKey = new oxField($this->getId(), oxField::T_RAW);
01305         $oDb = oxDb::getDb();
01306 
01307         $sUpdate= "update {$this->_sCoreTable} set " . $this->_getUpdateFields()
01308                  ." where {$this->_sCoreTable}.oxid = " . $oDb->quote( $this->getId() );
01309 
01310         //trigger event
01311         $this->beforeUpdate();
01312 
01313         $blRet = (bool) $oDb->execute( $sUpdate );
01314 
01315         return $blRet;
01316     }
01317 
01325     protected function _insert()
01326     {
01327 
01328         $oDb      = oxDb::getDb( oxDb::FETCH_MODE_ASSOC );
01329         $myConfig = $this->getConfig();
01330         $myUtils  = oxRegistry::getUtils();
01331 
01332         // let's get a new ID
01333         if ( !$this->getId()) {
01334             $this->setId();
01335         }
01336 
01337         $sIDKey = $myUtils->getArrFldName( $this->_sCoreTable . '.oxid' );
01338         $this->$sIDKey = new oxField( $this->getId(), oxField::T_RAW );
01339         $sInsert = "Insert into {$this->_sCoreTable} set ";
01340 
01341         //setting oxshopid
01342         $sShopField = $myUtils->getArrFldName( $this->_sCoreTable . '.oxshopid' );
01343 
01344         if ( isset( $this->$sShopField ) && !$this->$sShopField->value ) {
01345             $this->$sShopField = new oxField( $myConfig->getShopId(), oxField::T_RAW );
01346         }
01347 
01348 
01349         $sInsert .= $this->_getUpdateFields( $this->getUseSkipSaveFields() );
01350 
01351         $blRet = (bool) $oDb->execute( $sInsert );
01352 
01353         return $blRet;
01354     }
01355 
01362     protected function _isDisabledFieldCache()
01363     {
01364         $sClass = get_class( $this );
01365         if ( isset( self::$_blDisableFieldCaching[$sClass] ) && self::$_blDisableFieldCaching[$sClass] ) {
01366             return true;
01367         }
01368 
01369         return false;
01370     }
01371 
01377     public function isOx()
01378     {
01379         $sOxId = $this->getId();
01380         if ( $sOxId[0] == 'o' && $sOxId[1] == 'x' ) {
01381             return true;
01382         }
01383         return false;
01384     }
01385 
01391     public function isReadOnly()
01392     {
01393         return $this->_blReadOnly;
01394     }
01395 
01403     public function setReadOnly( $blReadOnly )
01404     {
01405         $this->_blReadOnly = $blReadOnly;
01406     }
01407 
01413     public function getFieldNames()
01414     {
01415         return array_keys( $this->_aFieldNames );
01416     }
01417 
01425     public function addFieldName( $sName )
01426     {
01427         //preparation
01428         $sName = strtolower( $sName );
01429         $this->_aFieldNames[$sName] = 0;
01430     }
01431 
01432 
01438     public function getLanguage()
01439     {
01440         return -1;
01441     }
01442 
01443 }