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         return $sSelect;
00643     }
00644 
00652     public function assignRecord( $sSelect )
00653     {
00654         $blRet = false;
00655 
00656         $rs = oxDb::getDb( oxDb::FETCH_MODE_ASSOC )->select( $sSelect );
00657 
00658         if ($rs != false && $rs->recordCount() > 0) {
00659             $blRet = true;
00660             $this->assign( $rs->fields);
00661         }
00662 
00663         return $blRet;
00664     }
00665 
00673     public function getFieldData( $sFieldName )
00674     {
00675         $sLongFieldName = $this->_getFieldLongName( $sFieldName );
00676             return $this->$sLongFieldName->value;
00677     }
00678 
00686     public function getSelectFields( $blForceCoreTableUsage = null )
00687     {
00688         $aSelectFields = array();
00689 
00690         $sViewName = $this->getViewName( $blForceCoreTableUsage );
00691 
00692         foreach ( $this->_aFieldNames as $sKey => $sField ) {
00693             if ( $sViewName ) {
00694                 $aSelectFields[] = "`$sViewName`.`$sKey`";
00695             } else {
00696                 $aSelectFields[] = ".`$sKey`";
00697             }
00698 
00699         }
00700 
00701         $sSelectFields = join( ', ', $aSelectFields );
00702         return $sSelectFields;
00703     }
00704 
00712     public function delete( $sOXID = null)
00713     {
00714         if ( !$sOXID ) {
00715             $sOXID = $this->getId();
00716 
00717             //do not allow derived deletion
00718             if ( !$this->allowDerivedDelete() ) {
00719                 return false;
00720             }
00721         }
00722 
00723         if ( !$sOXID ) {
00724             return false;
00725         }
00726 
00727 
00728         $oDB = oxDb::getDb( oxDb::FETCH_MODE_ASSOC );
00729         $sDelete = "delete from $this->_sCoreTable where oxid = " . $oDB->quote( $sOXID );
00730         $oDB->execute( $sDelete );
00731         if ( $blDelete = ( bool ) $oDB->affected_Rows() ) {
00732             $this->onChange( ACTION_DELETE, $sOXID );
00733         }
00734 
00735         return $blDelete;
00736     }
00737 
00738 
00744     public function save()
00745     {
00746         if ( !is_array( $this->_aFieldNames ) ) {
00747             return false;
00748         }
00749 
00750         // #739A - should be executed here because of date/time formatting feature
00751         if ( $this->isAdmin() && !$this->getConfig()->getConfigParam( 'blSkipFormatConversion' ) ) {
00752             foreach ($this->_aFieldNames as $sName => $sVal) {
00753                 $sLongName = $this->_getFieldLongName($sName);
00754                 if ( isset($this->$sLongName->fldtype) && $this->$sLongName->fldtype == 'datetime' ) {
00755                     oxRegistry::get('oxUtilsDate')->convertDBDateTime( $this->$sLongName, true );
00756                 } elseif ( isset($this->$sLongName->fldtype) && $this->$sLongName->fldtype == 'timestamp' ) {
00757                     oxRegistry::get('oxUtilsDate')->convertDBTimestamp( $this->$sLongName, true );
00758                 } elseif ( isset($this->$sLongName->fldtype) && $this->$sLongName->fldtype == 'date' ) {
00759                     oxRegistry::get('oxUtilsDate')->convertDBDate( $this->$sLongName, true );
00760                 }
00761             }
00762         }
00763         if ( $this->exists() ) {
00764             //do not allow derived update
00765             if ( !$this->allowDerivedUpdate() ) {
00766                 return false;
00767             }
00768 
00769             $blRet = $this->_update();
00770             $sAction = ACTION_UPDATE;
00771         } else {
00772             $blRet = $this->_insert();
00773             $sAction = ACTION_INSERT;
00774         }
00775 
00776         $this->onChange($sAction);
00777 
00778         if ( $blRet ) {
00779             return $this->getId();
00780         } else {
00781             return false;
00782         }
00783     }
00784 
00790     public function allowDerivedUpdate()
00791     {
00792         return !$this->isDerived();
00793     }
00794 
00800     public function allowDerivedDelete()
00801     {
00802         return !$this->isDerived();
00803     }
00804 
00812     public function exists( $sOXID = null)
00813     {
00814         if ( !$sOXID ) {
00815             $sOXID = $this->getId();
00816         }
00817         if ( !$sOXID ) {
00818             return false;
00819         }
00820 
00821         $sViewName = $this->getCoreTableName();
00822         $oDb = oxDb::getDb( oxDb::FETCH_MODE_ASSOC );
00823         $sSelect= "select {$this->_sExistKey} from {$sViewName} where {$this->_sExistKey} = " . $oDb->quote( $sOXID );
00824 
00825         return ( bool ) $oDb->getOne( $sSelect, false, false );
00826     }
00827 
00835     public function getSqlActiveSnippet( $blForceCoreTable = null )
00836     {
00837         $sQ = '';
00838         $sTable = $this->getViewName($blForceCoreTable);
00839 
00840         // has 'active' field ?
00841         if ( isset( $this->_aFieldNames['oxactive'] ) ) {
00842             $sQ = " $sTable.oxactive = 1 ";
00843         }
00844 
00845         // has 'activefrom'/'activeto' fields ?
00846         if ( isset( $this->_aFieldNames['oxactivefrom'] ) && isset( $this->_aFieldNames['oxactiveto'] ) ) {
00847 
00848             $sDate = date( 'Y-m-d H:i:s', oxRegistry::get('oxUtilsDate')->getTime() );
00849 
00850             $sQ = $sQ ? " $sQ or " : '';
00851             $sQ = " ( $sQ ( $sTable.oxactivefrom < '$sDate' and $sTable.oxactiveto > '$sDate' ) ) ";
00852         }
00853 
00854         return $sQ;
00855     }
00856 
00865     public function beforeUpdate( $sOXID = null )
00866     {
00867     }
00868 
00879     public function onChange( $iAction = null, $sOXID = null )
00880     {
00881     }
00882 
00883 
00889     public function setInList()
00890     {
00891         $this->_blIsInList = true;
00892     }
00893 
00899     protected function _isInList()
00900     {
00901         return $this->_blIsInList;
00902     }
00903 
00912     protected function _getObjectViewName( $sTable, $sShopID = null )
00913     {
00914         return getViewName( $sTable, -1, $sShopID);
00915     }
00916 
00917 
00928     protected function _getTableFields($sTable, $blReturnSimple = false )
00929     {
00930         $myUtils = oxRegistry::getUtils();
00931 
00932         $sCacheKey   = $sTable . '_allfields_' . $blReturnSimple;
00933         $aMetaFields = $myUtils->fromFileCache( $sCacheKey );
00934 
00935         if ( $aMetaFields ) {
00936             return $aMetaFields;
00937         }
00938 
00939         $aMetaFields = oxDb::getInstance()->getTableDescription( $sTable );
00940 
00941         if ( !$blReturnSimple ) {
00942             $myUtils->toFileCache( $sCacheKey, $aMetaFields );
00943             return $aMetaFields;
00944         }
00945 
00946         //returning simple array
00947         $aRet = array();
00948         if (is_array($aMetaFields)) {
00949             foreach ( $aMetaFields as $oVal ) {
00950                 $aRet[strtolower( $oVal->name )] = 0;
00951             }
00952         }
00953 
00954         $myUtils->toFileCache( $sCacheKey, $aRet);
00955 
00956         return $aRet;
00957     }
00958 
00970     protected function _getAllFields($blReturnSimple = false )
00971     {
00972         if (!$this->_sCoreTable) {
00973             return array();
00974         }
00975         return $this->_getTableFields($this->_sCoreTable, $blReturnSimple);
00976     }
00977 
00986     protected function _initDataStructure($blForceFullStructure = false )
00987     {
00988         $myUtils = oxRegistry::getUtils();
00989 
00990         //get field names from cache
00991         $aFieldNames = null;
00992         $sFullCacheKey = 'fieldnames_' . $this->_sCoreTable . '_' . $this->_sCacheKey;
00993         if ($this->_sCacheKey && !$this->_isDisabledFieldCache()) {
00994             $aFieldNames = $myUtils->fromFileCache( $sFullCacheKey );
00995         }
00996 
00997         if (!$aFieldNames) {
00998             $aFieldNames = $this->_getNonCachedFieldNames( $blForceFullStructure );
00999             if ($this->_sCacheKey && !$this->_isDisabledFieldCache()) {
01000                 $myUtils->toFileCache( $sFullCacheKey, $aFieldNames );
01001             }
01002         }
01003 
01004         if ( $aFieldNames !== false ) {
01005             foreach ( $aFieldNames as $sField => $sStatus ) {
01006                 $this->_addField( $sField, $sStatus );
01007             }
01008         }
01009     }
01010 
01022     protected function _getNonCachedFieldNames( $blForceFullStructure = false )
01023     {
01024         //T2008-02-22
01025         //so if this method is executed on cached version we see it when profiling
01026         startProfile('!__CACHABLE__!');
01027 
01028         //case 1. (admin)
01029         if ($this->isAdmin()) {
01030             $aMetaFields = $this->_getAllFields();
01031             foreach ( $aMetaFields as $oField ) {
01032                 if ( $oField->max_length == -1 ) {
01033                     $oField->max_length = 10;      // double or float
01034                 }
01035 
01036                 if ( $oField->type == 'datetime' ) {
01037                     $oField->max_length = 20;
01038                 }
01039 
01040                 $this->_addField( $oField->name, $this->_getFieldStatus($oField->name), $oField->type, $oField->max_length );
01041             }
01042             stopProfile('!__CACHABLE__!');
01043             return false;
01044         }
01045 
01046         //case 2. (just get all fields)
01047         if ( $blForceFullStructure || !$this->_blUseLazyLoading ) {
01048             $aMetaFields = $this->_getAllFields(true);
01049             /*
01050             foreach ( $aMetaFields as $sFieldName => $sVal) {
01051                 $this->_addField( $sFieldName, $this->_getFieldStatus($sFieldName));
01052             }*/
01053             stopProfile('!__CACHABLE__!');
01054             return $aMetaFields;
01055         }
01056 
01057         //case 3. (get only oxid field, so we can fetch the rest of the fields over lazy loading mechanism)
01058         stopProfile('!__CACHABLE__!');
01059         return array('oxid' => 0);
01060     }
01061 
01070     protected function _getFieldStatus( $sFieldName )
01071     {
01072         return 0;
01073     }
01074 
01085     protected function _addField($sName, $iStatus, $sType = null, $sLength = null )
01086     {
01087         //preparation
01088         $sName = strtolower( $sName );
01089 
01090         //adding field names element
01091         $this->_aFieldNames[$sName] = $iStatus;
01092 
01093         //already set?
01094         $sLongName = $this->_getFieldLongName( $sName );
01095         if ( isset($this->$sLongName) ) {
01096             return;
01097         }
01098 
01099         //defining the field
01100         $oField = false;
01101 
01102         if ( isset( $sType ) ) {
01103             $oField = new oxField();
01104             $oField->fldtype = $sType;
01105             //T2008-01-29
01106             //can't clone as the fields are objects and are not fully cloned
01107             $this->_blIsSimplyClonable = false;
01108         }
01109 
01110         if ( isset( $sLength ) ) {
01111             if ( !$oField ) {
01112                 $oField = new oxField();
01113             }
01114             $oField->fldmax_length = $sLength;
01115             $this->_blIsSimplyClonable = false;
01116         }
01117 
01118         $this->$sLongName = $oField;
01119     }
01120 
01128     protected function _getFieldLongName( $sFieldName )
01129     {
01130         //trying to avoid strpos call as often as possible
01131         if ( $sFieldName[2] == $this->_sCoreTable[2] && strpos( $sFieldName, $this->_sCoreTable . '__' ) === 0 ) {
01132             return $sFieldName;
01133         }
01134 
01135         return $this->_sCoreTable . '__' . strtolower( $sFieldName );
01136     }
01137 
01147     protected function _setFieldData( $sFieldName, $sValue, $iDataType = oxField::T_TEXT )
01148     {
01149 
01150         $sLongFieldName = $this->_getFieldLongName( $sFieldName);
01151         //$sLongFieldName = $this->_sCoreTable . "__" . strtolower($sFieldName);
01152 
01153         //T2008-03-14
01154         //doing this because in lazy loaded lists on first load it is harmful to have initialised fields but not yet set
01155         //situation: only first article is loaded fully for "select oxid from oxarticles"
01156         /*
01157         if ($this->_blUseLazyLoading && !isset($this->$sLongFieldName))
01158             return;*/
01159 
01160         //in non lazy loading case we just add a field and do not care about it more
01161         if (!$this->_blUseLazyLoading && !isset( $this->$sLongFieldName )) {
01162             $aFields = $this->_getAllFields(true);
01163             if ( isset( $aFields[strtolower( $sFieldName )] ) ) {
01164                 $this->_addField( $sFieldName, $this->_getFieldStatus( $sFieldName ) );
01165             }
01166         }
01167         // if we have a double field we replace "," with "." in case somebody enters it in european format
01168         if (isset($this->$sLongFieldName) && isset( $this->$sLongFieldName->fldtype ) && $this->$sLongFieldName->fldtype == 'double') {
01169             $sValue = str_replace( ',', '.', $sValue );
01170         }
01171 
01172         // isset is REQUIRED here not to use getter
01173         if ( isset( $this->$sLongFieldName ) && is_object( $this->$sLongFieldName ) ) {
01174             $this->$sLongFieldName->setValue( $sValue, $iDataType );
01175         } else {
01176             $this->$sLongFieldName = new oxField( $sValue, $iDataType );
01177         }
01178 
01179     }
01180 
01188     protected function _canFieldBeNull( $sFieldName )
01189     {
01190         $aMetaData = $this->_getAllFields();
01191         foreach ( $aMetaData as $oMetaInfo ) {
01192             if ( strcasecmp( $oMetaInfo->name, $sFieldName ) == 0 ) {
01193                 return !$oMetaInfo->not_null;
01194             }
01195         }
01196         return false;
01197     }
01198 
01206     protected function _getFieldDefaultValue( $sFieldName )
01207     {
01208         $aMetaData = $this->_getAllFields();
01209         foreach ( $aMetaData as $oMetaInfo ) {
01210             if ( strcasecmp( $oMetaInfo->name, $sFieldName ) == 0 ) {
01211                 return $oMetaInfo->default_value;
01212             }
01213         }
01214         return false;
01215     }
01216 
01225     protected function _getUpdateFieldValue( $sFieldName, $oField )
01226     {
01227         $mValue = null;
01228         if ( $oField instanceof oxField ) {
01229             $mValue = $oField->getRawValue();
01230         } elseif ( isset( $oField->value ) ) {
01231             $mValue = $oField->value;
01232         }
01233 
01234         $oDb = oxDb::getDb();
01235         //Check if this field value is null AND it can be null according if not returning default value
01236         if ( ( null === $mValue ) ) {
01237             if ( $this->_canFieldBeNull( $sFieldName ) ) {
01238                 return 'null';
01239             } elseif ( $mValue = $this->_getFieldDefaultValue( $sFieldName ) ) {
01240                 return $oDb->quote( $mValue );
01241             }
01242         }
01243 
01244         return $oDb->quote( $mValue );
01245     }
01246 
01255     protected function _getUpdateFields( $blUseSkipSaveFields = true )
01256     {
01257         $sSql = '';
01258         $blSep  = false;
01259 
01260         foreach ( array_keys( $this->_aFieldNames ) as $sKey ) {
01261             $sLongName = $this->_getFieldLongName( $sKey );
01262             $oField = $this->$sLongName;
01263 
01264 
01265             if ( !$blUseSkipSaveFields || ( $blUseSkipSaveFields && !in_array( strtolower( $sKey ), $this->_aSkipSaveFields ) ) ) {
01266                 $sSql .= (( $blSep) ? ',' : '' ) . $sKey . ' = ' . $this->_getUpdateFieldValue( $sKey, $oField );
01267                 $blSep = true;
01268             }
01269         }
01270 
01271         return $sSql;
01272     }
01273 
01283     protected function _update()
01284     {
01285         //do not allow derived item update
01286         if ( !$this->allowDerivedUpdate() ) {
01287             return false;
01288         }
01289 
01290 
01291         if ( !$this->getId() ) {
01295             $oEx = oxNew( 'oxObjectException' );
01296             $oEx->setMessage( 'EXCEPTION_OBJECT_OXIDNOTSET' );
01297             $oEx->setObject($this);
01298             throw $oEx;
01299         }
01300 
01301         $sIDKey = oxRegistry::getUtils()->getArrFldName( $this->_sCoreTable . '.oxid' );
01302         $this->$sIDKey = new oxField($this->getId(), oxField::T_RAW);
01303         $oDb = oxDb::getDb();
01304 
01305         $sUpdate= "update {$this->_sCoreTable} set " . $this->_getUpdateFields()
01306                  ." where {$this->_sCoreTable}.oxid = " . $oDb->quote( $this->getId() );
01307 
01308         //trigger event
01309         $this->beforeUpdate();
01310 
01311         $blRet = (bool) $oDb->execute( $sUpdate );
01312 
01313         return $blRet;
01314     }
01315 
01323     protected function _insert()
01324     {
01325 
01326         $oDb      = oxDb::getDb( oxDb::FETCH_MODE_ASSOC );
01327         $myConfig = $this->getConfig();
01328         $myUtils  = oxRegistry::getUtils();
01329 
01330         // let's get a new ID
01331         if ( !$this->getId()) {
01332             $this->setId();
01333         }
01334 
01335         $sIDKey = $myUtils->getArrFldName( $this->_sCoreTable . '.oxid' );
01336         $this->$sIDKey = new oxField( $this->getId(), oxField::T_RAW );
01337         $sInsert = "Insert into {$this->_sCoreTable} set ";
01338 
01339         //setting oxshopid
01340         $sShopField = $myUtils->getArrFldName( $this->_sCoreTable . '.oxshopid' );
01341 
01342         if ( isset( $this->$sShopField ) && !$this->$sShopField->value ) {
01343             $this->$sShopField = new oxField( $myConfig->getShopId(), oxField::T_RAW );
01344         }
01345 
01346 
01347         $sInsert .= $this->_getUpdateFields( $this->getUseSkipSaveFields() );
01348 
01349         $blRet = (bool) $oDb->execute( $sInsert );
01350 
01351         return $blRet;
01352     }
01353 
01360     protected function _isDisabledFieldCache()
01361     {
01362         $sClass = get_class( $this );
01363         if ( isset( self::$_blDisableFieldCaching[$sClass] ) && self::$_blDisableFieldCaching[$sClass] ) {
01364             return true;
01365         }
01366 
01367         return false;
01368     }
01369 
01375     public function isOx()
01376     {
01377         $sOxId = $this->getId();
01378         if ( $sOxId[0] == 'o' && $sOxId[1] == 'x' ) {
01379             return true;
01380         }
01381         return false;
01382     }
01383 
01389     public function isReadOnly()
01390     {
01391         return $this->_blReadOnly;
01392     }
01393 
01401     public function setReadOnly( $blReadOnly )
01402     {
01403         $this->_blReadOnly = $blReadOnly;
01404     }
01405 
01411     public function getFieldNames()
01412     {
01413         return array_keys( $this->_aFieldNames );
01414     }
01415 
01423     public function addFieldName( $sName )
01424     {
01425         //preparation
01426         $sName = strtolower( $sName );
01427         $this->_aFieldNames[$sName] = 0;
01428     }
01429 
01430 
01436     public function getLanguage()
01437     {
01438         return -1;
01439     }
01440 
01441 }