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 $_blUpdateSeo = true;
00130 
00136     protected $_blReadOnly = false;
00137 
00143     protected $_blIsInList = false;
00144 
00150     protected $_isLoaded = false;
00151 
00157     protected $_aInnerLazyCache = null;
00158 
00164     protected $_blEmployMultilanguage = false;
00165 
00166 
00172     public function getUseSkipSaveFields()
00173     {
00174         return $this->_blUseSkipSaveFields;
00175     }
00176 
00184     public function setUseSkipSaveFields( $blUseSkipSaveFields )
00185     {
00186         $this->_blUseSkipSaveFields = $blUseSkipSaveFields;
00187     }
00188 
00192     public function __construct()
00193     {
00194         // set active shop
00195         $myConfig = $this->getConfig();
00196         $this->_sCacheKey = $this->getViewName();
00197 
00198 
00199         if ( $this->_blUseLazyLoading ) {
00200             $this->_sCacheKey .= $myConfig->getActiveView()->getClassName();
00201         } else {
00202             $this->_sCacheKey .= 'allviews';
00203         }
00204 
00205         //do not cache for admin?
00206         if ( $this->isAdmin() ) {
00207             $this->_sCacheKey = null;
00208         }
00209 
00210         $this->setShopId( $myConfig->getShopId() );
00211     }
00212 
00221     public function __set( $sName, $sValue )
00222     {
00223         $this->$sName = $sValue;
00224         if ( $this->_blUseLazyLoading && strpos( $sName, $this->_sCoreTable . '__' ) === 0 ) {
00225             $sFieldName = str_replace( $this->_sCoreTable . "__", '', $sName );
00226             if ( $sFieldName != 'oxnid' && ( !isset( $this->_aFieldNames[$sFieldName] ) || !$this->_aFieldNames[$sFieldName] ) ) {
00227                 $aAllFields = $this->_getAllFields(true);
00228                 if ( isset( $aAllFields[strtolower($sFieldName)] ) ) {
00229                     $iFieldStatus = $this->_getFieldStatus( $sFieldName );
00230                     $this->_addField( $sFieldName, $iFieldStatus );
00231                 }
00232             }
00233         }
00234     }
00235 
00243     public function __get( $sName )
00244     {
00245         switch ( $sName ) {
00246             case 'blIsDerived':
00247                 return $this->isDerived();
00248                 break;
00249             case 'sOXID':
00250                 return $this->getId();
00251                 break;
00252             case 'blReadOnly':
00253                 return $this->isReadOnly();
00254                 break;
00255         }
00256 
00257         // implementing lazy loading fields
00258         // This part of the code is slow and normally is called before field cache is built.
00259         // Make sure it is not called after first page is loaded and cache data is fully built.
00260         if ( $this->_blUseLazyLoading && stripos( $sName, $this->_sCoreTable . "__" ) === 0 ) {
00261 
00262             if ( $this->getId() ) {
00263 
00264                 //lazy load it
00265                 $sFieldName      = str_replace( $this->_sCoreTable . '__', '', $sName );
00266                 $sCacheFieldName = strtoupper( $sFieldName );
00267 
00268                 $iFieldStatus = $this->_getFieldStatus( $sFieldName );
00269                 $sViewName    = $this->getViewName();
00270                 $sId = $this->getId();
00271 
00272                 try {
00273                     if ( $this->_aInnerLazyCache === null ) {
00274 
00275                         $oDb = oxDb::getDb( oxDb::FETCH_MODE_ASSOC );
00276                         $sQ = 'SELECT * FROM ' . $sViewName . ' WHERE `oxid` = ' . $oDb->quote( $sId );
00277                         $rs = $oDb->select( $sQ );
00278                         if ( $rs && $rs->RecordCount() ) {
00279                             $this->_aInnerLazyCache = array_change_key_case( $rs->fields, CASE_UPPER );
00280                             if ( array_key_exists( $sCacheFieldName, $this->_aInnerLazyCache ) ) {
00281                                 $sFieldValue = $this->_aInnerLazyCache[$sCacheFieldName];
00282                             } else {
00283                                 return null;
00284                             }
00285                         } else {
00286                             return null;
00287                         }
00288                     } elseif ( array_key_exists( $sCacheFieldName, $this->_aInnerLazyCache ) ) {
00289                         $sFieldValue = $this->_aInnerLazyCache[$sCacheFieldName];
00290                     } else {
00291                         return null;
00292                     }
00293 
00294                     $this->_addField( $sFieldName, $iFieldStatus );
00295                     $this->_setFieldData( $sFieldName, $sFieldValue );
00296 
00297                     //save names to cache for next loading
00298                     if ($this->_sCacheKey) {
00299                         $myUtils = oxRegistry::getUtils();
00300                         $sCacheKey = 'fieldnames_' . $this->_sCoreTable . '_' . $this->_sCacheKey;
00301                         $aFieldNames = $myUtils->fromFileCache( $sCacheKey );
00302                         $aFieldNames[$sFieldName] = $iFieldStatus;
00303                         $myUtils->toFileCache( $sCacheKey, $aFieldNames );
00304                     }
00305                 } catch ( Exception $e ) {
00306                     return null;
00307                 }
00308 
00309                 //do not use field cache for this page
00310                 //as if we use it for lists then objects are loaded empty instead of lazy loading.
00311                 self::$_blDisableFieldCaching[get_class( $this )] = true;
00312             }
00313 
00314             oxUtilsObject::getInstance()->resetInstanceCache(get_class($this));
00315         }
00316 
00317         //returns stdClass implementing __toString() method due to uknown scenario where this var should be used.
00318         if (!isset( $this->$sName ) ) {
00319             $this->$sName = null;
00320         }
00321 
00322         return $this->$sName;
00323     }
00324 
00332     public function __isset($mVar)
00333     {
00334         return isset($this->$mVar);
00335     }
00336 
00342     public function __clone()
00343     {
00344         if (!$this->_blIsSimplyClonable) {
00345             foreach ( $this->_aFieldNames as $sField => $sVal ) {
00346                 $sLongName = $this->_getFieldLongName( $sField );
00347                 if ( is_object($this->$sLongName)) {
00348                     $this->$sLongName = clone $this->$sLongName;
00349                 }
00350             }
00351         }
00352     }
00353 
00361     public function oxClone( $oObject )
00362     {
00363         $aClasVars = get_object_vars( $oObject );
00364         while (list($name, $value) = each( $aClasVars )) {
00365             if ( is_object( $oObject->$name ) ) {
00366                 $this->$name = clone $oObject->$name;
00367             } else {
00368                 $this->$name = $oObject->$name;
00369             }
00370         }
00371     }
00372 
00378     public function getUpdateSeo()
00379     {
00380         return $this->_blUpdateSeo;
00381     }
00382 
00388     public function setUpdateSeo($blUpdateSeo)
00389     {
00390         $this->_blUpdateSeo = $blUpdateSeo;
00391     }
00392 
00400     protected function _setUpdateSeoOnFieldChange($sField)
00401     {
00402         if ($this->getId() && in_array($sField, $this->getFieldNames())) {
00403             $oDb = oxDb::getDb();
00404             $sTableName = $this->getCoreTableName();
00405             $sQuotedOxid = $oDb->quote($this->getId());
00406             $sTitle = $oDb->getOne("select `{$sField}` from `{$sTableName}` where `oxid` = {$sQuotedOxid}");
00407             $sFieldValue = "{$sTableName}__{$sField}";
00408             $sCurrentTitle = $this->$sFieldValue->value;
00409 
00410             if ($sTitle == $sCurrentTitle) {
00411                 $this->setUpdateSeo(false);
00412             }
00413         }
00414     }
00415 
00424     public function init( $sTableName = null, $blForceAllFields = false )
00425     {
00426         if ( $sTableName ) {
00427             $this->_sCoreTable = $sTableName;
00428         }
00429 
00430         // reset view table
00431         $this->_sViewTable = false;
00432 
00433         if ( count( $this->_aFieldNames ) <= 1 ) {
00434             $this->_initDataStructure( $blForceAllFields );
00435         }
00436     }
00437 
00445     public function assign( $dbRecord )
00446     {
00447         if ( !is_array( $dbRecord ) ) {
00448             return;
00449         }
00450 
00451 
00452         reset($dbRecord );
00453         while ( list( $sName, $sValue ) = each( $dbRecord ) ) {
00454 
00455             // patch for IIS
00456             //TODO: test it on IIS do we still need it
00457             //if( is_array($value) && count( $value) == 1)
00458             //    $value = current( $value);
00459 
00460             $this->_setFieldData( $sName, $sValue );
00461         }
00462 
00463         $sOxidField = $this->_getFieldLongName( 'oxid' );
00464         $this->_sOXID = $this->$sOxidField->value;
00465 
00466     }
00467 
00473     public function getClassName()
00474     {
00475         return $this->_sClassName;
00476     }
00477 
00483     public function getCoreTableName()
00484     {
00485         return $this->_sCoreTable;
00486     }
00487 
00493     public function getId()
00494     {
00495         return $this->_sOXID;
00496     }
00497 
00505     public function setId( $sOXID = null )
00506     {
00507         if ( $sOXID ) {
00508             $this->_sOXID = $sOXID;
00509         } else {
00510             $this->_sOXID = oxUtilsObject::getInstance()->generateUID();
00511         }
00512 
00513         $sIdVarName = $this->_sCoreTable . '__oxid';
00514         $this->$sIdVarName = new oxField($this->_sOXID, oxField::T_RAW);
00515 
00516         return $this->_sOXID;
00517     }
00518 
00526     public function setShopId( $iShopId )
00527     {
00528         $this->_iShopId = $iShopId;
00529     }
00530 
00536     public function getShopId()
00537     {
00538         return $this->_iShopId;
00539     }
00540 
00548     public function getViewName( $blForceCoreTableUsage = null )
00549     {
00550         if (!$this->_sViewTable || ( $blForceCoreTableUsage !== null )) {
00551             if ( $blForceCoreTableUsage === true ) {
00552                 return $this->_sCoreTable;
00553             }
00554 
00555 
00556             if ( ( $blForceCoreTableUsage !== null ) && $blForceCoreTableUsage ) {
00557                 $iShopId = -1;
00558             } else {
00559                 $iShopId = oxRegistry::getConfig()->getShopId();
00560             }
00561 
00562             $sViewName = getViewName( $this->_sCoreTable, $this->_blEmployMultilanguage == false ? -1 : $this->getLanguage(), $iShopId );
00563             if ( $blForceCoreTableUsage !== null ) {
00564                 return $sViewName;
00565             }
00566             $this->_sViewTable = $sViewName;
00567         }
00568         return $this->_sViewTable;
00569     }
00570 
00579     public function modifyCacheKey( $sCacheKey, $blOverride = false )
00580     {
00581         if ( $blOverride ) {
00582             $this->_sCacheKey = $sCacheKey;
00583         } else {
00584             $this->_sCacheKey .= $sCacheKey;
00585         }
00586     }
00587 
00593     public function disableLazyLoading()
00594     {
00595         $this->_blUseLazyLoading = false;
00596         $this->_initDataStructure(true);
00597     }
00598 
00599 
00605     public function isDerived()
00606     {
00607 
00608         return $this->_blIsDerived;
00609     }
00610 
00618     public function setIsDerived( $blVal )
00619     {
00620         $this->_blIsDerived = $blVal;
00621     }
00622 
00629     public function isMultilang()
00630     {
00631         return false;
00632     }
00633 
00643     public function load( $sOXID )
00644     {
00645         $blExistingOldForceCoreTable = $this->_blForceCoreTableUsage;
00646 
00647         $this->_blForceCoreTableUsage = true;
00648 
00649         //getting at least one field before lazy loading the object
00650         $this->_addField( 'oxid', 0 );
00651         $sSelect = $this->buildSelectString( array( $this->getViewName() . '.oxid' => $sOXID) );
00652         $this->_isLoaded = $this->assignRecord( $sSelect );
00653 
00654         $this->_blForceCoreTableUsage = $blExistingOldForceCoreTable;
00655 
00656         return $this->_isLoaded;
00657     }
00658 
00664     public function isLoaded()
00665     {
00666         return $this->_isLoaded;
00667     }
00668 
00676     public function buildSelectString( $aWhere = null)
00677     {
00678         $oDB = oxDb::getDb();
00679 
00680         $sGet = $this->getSelectFields();
00681         $sSelect = "select $sGet from " . $this->getViewName() . ' where 1 ';
00682 
00683         if ( $aWhere) {
00684             reset($aWhere);
00685             while (list($name, $value) = each($aWhere)) {
00686                 $sSelect .=  ' and ' . $name . ' = '.$oDB->quote($value);
00687             }
00688         }
00689 
00690         // add active shop
00691 
00692         return $sSelect;
00693     }
00694 
00702     public function assignRecord( $sSelect )
00703     {
00704         $blRet = false;
00705 
00706         $rs = oxDb::getDb( oxDb::FETCH_MODE_ASSOC )->select( $sSelect );
00707 
00708         if ($rs != false && $rs->recordCount() > 0) {
00709             $blRet = true;
00710             $this->assign( $rs->fields);
00711         }
00712 
00713         return $blRet;
00714     }
00715 
00723     public function getFieldData( $sFieldName )
00724     {
00725         $sLongFieldName = $this->_getFieldLongName( $sFieldName );
00726             return $this->$sLongFieldName->value;
00727     }
00728 
00736     public function getSelectFields( $blForceCoreTableUsage = null )
00737     {
00738         $aSelectFields = array();
00739 
00740         $sViewName = $this->getViewName( $blForceCoreTableUsage );
00741 
00742         foreach ( $this->_aFieldNames as $sKey => $sField ) {
00743             if ( $sViewName ) {
00744                 $aSelectFields[] = "`$sViewName`.`$sKey`";
00745             } else {
00746                 $aSelectFields[] = ".`$sKey`";
00747             }
00748 
00749         }
00750 
00751         $sSelectFields = join( ', ', $aSelectFields );
00752         return $sSelectFields;
00753     }
00754 
00762     public function delete( $sOXID = null)
00763     {
00764         if ( !$sOXID ) {
00765             $sOXID = $this->getId();
00766 
00767             //do not allow derived deletion
00768             if ( !$this->allowDerivedDelete() ) {
00769                 return false;
00770             }
00771         }
00772 
00773         if ( !$sOXID ) {
00774             return false;
00775         }
00776 
00777 
00778         $oDB = oxDb::getDb( oxDb::FETCH_MODE_ASSOC );
00779         $sDelete = "delete from $this->_sCoreTable where oxid = " . $oDB->quote( $sOXID );
00780         $oDB->execute( $sDelete );
00781         if ( $blDelete = ( bool ) $oDB->affected_Rows() ) {
00782             $this->onChange( ACTION_DELETE, $sOXID );
00783         }
00784 
00785         return $blDelete;
00786     }
00787 
00788 
00794     public function save()
00795     {
00796         if ( !is_array( $this->_aFieldNames ) ) {
00797             return false;
00798         }
00799 
00800         // #739A - should be executed here because of date/time formatting feature
00801         if ( $this->isAdmin() && !$this->getConfig()->getConfigParam( 'blSkipFormatConversion' ) ) {
00802             foreach ($this->_aFieldNames as $sName => $sVal) {
00803                 $sLongName = $this->_getFieldLongName($sName);
00804                 if ( isset($this->$sLongName->fldtype) && $this->$sLongName->fldtype == 'datetime' ) {
00805                     oxRegistry::get('oxUtilsDate')->convertDBDateTime( $this->$sLongName, true );
00806                 } elseif ( isset($this->$sLongName->fldtype) && $this->$sLongName->fldtype == 'timestamp' ) {
00807                     oxRegistry::get('oxUtilsDate')->convertDBTimestamp( $this->$sLongName, true );
00808                 } elseif ( isset($this->$sLongName->fldtype) && $this->$sLongName->fldtype == 'date' ) {
00809                     oxRegistry::get('oxUtilsDate')->convertDBDate( $this->$sLongName, true );
00810                 }
00811             }
00812         }
00813         if ( $this->exists() ) {
00814             //do not allow derived update
00815             if ( !$this->allowDerivedUpdate() ) {
00816                 return false;
00817             }
00818 
00819             $blRet = $this->_update();
00820             $sAction = ACTION_UPDATE;
00821         } else {
00822             $blRet = $this->_insert();
00823             $sAction = ACTION_INSERT;
00824         }
00825 
00826         $this->onChange($sAction);
00827 
00828         if ( $blRet ) {
00829             return $this->getId();
00830         } else {
00831             return false;
00832         }
00833     }
00834 
00840     public function allowDerivedUpdate()
00841     {
00842         return !$this->isDerived();
00843     }
00844 
00850     public function allowDerivedDelete()
00851     {
00852         return !$this->isDerived();
00853     }
00854 
00862     public function exists( $sOXID = null)
00863     {
00864         if ( !$sOXID ) {
00865             $sOXID = $this->getId();
00866         }
00867         if ( !$sOXID ) {
00868             return false;
00869         }
00870 
00871         $sViewName = $this->getCoreTableName();
00872         $oDb = oxDb::getDb( oxDb::FETCH_MODE_ASSOC );
00873         $sSelect= "select {$this->_sExistKey} from {$sViewName} where {$this->_sExistKey} = " . $oDb->quote( $sOXID );
00874 
00875         return ( bool ) $oDb->getOne( $sSelect, false, false );
00876     }
00877 
00885     public function getSqlActiveSnippet( $blForceCoreTable = null )
00886     {
00887         $sQ = '';
00888         $sTable = $this->getViewName($blForceCoreTable);
00889 
00890         // has 'active' field ?
00891         if ( isset( $this->_aFieldNames['oxactive'] ) ) {
00892             $sQ = " $sTable.oxactive = 1 ";
00893         }
00894 
00895         // has 'activefrom'/'activeto' fields ?
00896         if ( isset( $this->_aFieldNames['oxactivefrom'] ) && isset( $this->_aFieldNames['oxactiveto'] ) ) {
00897 
00898             $sDate = date( 'Y-m-d H:i:s', oxRegistry::get('oxUtilsDate')->getTime() );
00899 
00900             $sQ = $sQ ? " $sQ or " : '';
00901             $sQ = " ( $sQ ( $sTable.oxactivefrom < '$sDate' and $sTable.oxactiveto > '$sDate' ) ) ";
00902         }
00903 
00904         return $sQ;
00905     }
00906 
00915     public function beforeUpdate( $sOXID = null )
00916     {
00917     }
00918 
00929     public function onChange( $iAction = null, $sOXID = null )
00930     {
00931     }
00932 
00933 
00939     public function setInList()
00940     {
00941         $this->_blIsInList = true;
00942     }
00943 
00949     protected function _isInList()
00950     {
00951         return $this->_blIsInList;
00952     }
00953 
00962     protected function _getObjectViewName( $sTable, $sShopID = null )
00963     {
00964         return getViewName( $sTable, -1, $sShopID);
00965     }
00966 
00967 
00978     protected function _getTableFields($sTable, $blReturnSimple = false )
00979     {
00980         $myUtils = oxRegistry::getUtils();
00981 
00982         $sCacheKey   = $sTable . '_allfields_' . $blReturnSimple;
00983         $aMetaFields = $myUtils->fromFileCache( $sCacheKey );
00984 
00985         if ( $aMetaFields ) {
00986             return $aMetaFields;
00987         }
00988 
00989         $aMetaFields = oxDb::getInstance()->getTableDescription( $sTable );
00990 
00991         if ( !$blReturnSimple ) {
00992             $myUtils->toFileCache( $sCacheKey, $aMetaFields );
00993             return $aMetaFields;
00994         }
00995 
00996         //returning simple array
00997         $aRet = array();
00998         if (is_array($aMetaFields)) {
00999             foreach ( $aMetaFields as $oVal ) {
01000                 $aRet[strtolower( $oVal->name )] = 0;
01001             }
01002         }
01003 
01004         $myUtils->toFileCache( $sCacheKey, $aRet);
01005 
01006         return $aRet;
01007     }
01008 
01020     protected function _getAllFields($blReturnSimple = false )
01021     {
01022         if (!$this->_sCoreTable) {
01023             return array();
01024         }
01025         return $this->_getTableFields($this->_sCoreTable, $blReturnSimple);
01026     }
01027 
01036     protected function _initDataStructure($blForceFullStructure = false )
01037     {
01038         $myUtils = oxRegistry::getUtils();
01039 
01040         //get field names from cache
01041         $aFieldNames = null;
01042         $sFullCacheKey = 'fieldnames_' . $this->_sCoreTable . '_' . $this->_sCacheKey;
01043         if ($this->_sCacheKey && !$this->_isDisabledFieldCache()) {
01044             $aFieldNames = $myUtils->fromFileCache( $sFullCacheKey );
01045         }
01046 
01047         if (!$aFieldNames) {
01048             $aFieldNames = $this->_getNonCachedFieldNames( $blForceFullStructure );
01049             if ($this->_sCacheKey && !$this->_isDisabledFieldCache()) {
01050                 $myUtils->toFileCache( $sFullCacheKey, $aFieldNames );
01051             }
01052         }
01053 
01054         if ( $aFieldNames !== false ) {
01055             foreach ( $aFieldNames as $sField => $sStatus ) {
01056                 $this->_addField( $sField, $sStatus );
01057             }
01058         }
01059     }
01060 
01072     protected function _getNonCachedFieldNames( $blForceFullStructure = false )
01073     {
01074         //T2008-02-22
01075         //so if this method is executed on cached version we see it when profiling
01076         startProfile('!__CACHABLE__!');
01077 
01078         //case 1. (admin)
01079         if ($this->isAdmin()) {
01080             $aMetaFields = $this->_getAllFields();
01081             foreach ( $aMetaFields as $oField ) {
01082                 if ( $oField->max_length == -1 ) {
01083                     $oField->max_length = 10;      // double or float
01084                 }
01085 
01086                 if ( $oField->type == 'datetime' ) {
01087                     $oField->max_length = 20;
01088                 }
01089 
01090                 $this->_addField( $oField->name, $this->_getFieldStatus($oField->name), $oField->type, $oField->max_length );
01091             }
01092             stopProfile('!__CACHABLE__!');
01093             return false;
01094         }
01095 
01096         //case 2. (just get all fields)
01097         if ( $blForceFullStructure || !$this->_blUseLazyLoading ) {
01098             $aMetaFields = $this->_getAllFields(true);
01099             /*
01100             foreach ( $aMetaFields as $sFieldName => $sVal) {
01101                 $this->_addField( $sFieldName, $this->_getFieldStatus($sFieldName));
01102             }*/
01103             stopProfile('!__CACHABLE__!');
01104             return $aMetaFields;
01105         }
01106 
01107         //case 3. (get only oxid field, so we can fetch the rest of the fields over lazy loading mechanism)
01108         stopProfile('!__CACHABLE__!');
01109         return array('oxid' => 0);
01110     }
01111 
01120     protected function _getFieldStatus( $sFieldName )
01121     {
01122         return 0;
01123     }
01124 
01135     protected function _addField($sName, $iStatus, $sType = null, $sLength = null )
01136     {
01137         //preparation
01138         $sName = strtolower( $sName );
01139 
01140         //adding field names element
01141         $this->_aFieldNames[$sName] = $iStatus;
01142 
01143         //already set?
01144         $sLongName = $this->_getFieldLongName( $sName );
01145         if ( isset($this->$sLongName) ) {
01146             return;
01147         }
01148 
01149         //defining the field
01150         $oField = false;
01151 
01152         if ( isset( $sType ) ) {
01153             $oField = new oxField();
01154             $oField->fldtype = $sType;
01155             //T2008-01-29
01156             //can't clone as the fields are objects and are not fully cloned
01157             $this->_blIsSimplyClonable = false;
01158         }
01159 
01160         if ( isset( $sLength ) ) {
01161             if ( !$oField ) {
01162                 $oField = new oxField();
01163             }
01164             $oField->fldmax_length = $sLength;
01165             $this->_blIsSimplyClonable = false;
01166         }
01167 
01168         $this->$sLongName = $oField;
01169     }
01170 
01178     protected function _getFieldLongName( $sFieldName )
01179     {
01180         //trying to avoid strpos call as often as possible
01181         if ( $sFieldName[2] == $this->_sCoreTable[2] && strpos( $sFieldName, $this->_sCoreTable . '__' ) === 0 ) {
01182             return $sFieldName;
01183         }
01184 
01185         return $this->_sCoreTable . '__' . strtolower( $sFieldName );
01186     }
01187 
01197     protected function _setFieldData( $sFieldName, $sValue, $iDataType = oxField::T_TEXT )
01198     {
01199 
01200         $sLongFieldName = $this->_getFieldLongName( $sFieldName);
01201         //$sLongFieldName = $this->_sCoreTable . "__" . strtolower($sFieldName);
01202 
01203         //T2008-03-14
01204         //doing this because in lazy loaded lists on first load it is harmful to have initialised fields but not yet set
01205         //situation: only first article is loaded fully for "select oxid from oxarticles"
01206         /*
01207         if ($this->_blUseLazyLoading && !isset($this->$sLongFieldName))
01208             return;*/
01209 
01210         //in non lazy loading case we just add a field and do not care about it more
01211         if (!$this->_blUseLazyLoading && !isset( $this->$sLongFieldName )) {
01212             $aFields = $this->_getAllFields(true);
01213             if ( isset( $aFields[strtolower( $sFieldName )] ) ) {
01214                 $this->_addField( $sFieldName, $this->_getFieldStatus( $sFieldName ) );
01215             }
01216         }
01217         // if we have a double field we replace "," with "." in case somebody enters it in european format
01218         if (isset($this->$sLongFieldName) && isset( $this->$sLongFieldName->fldtype ) && $this->$sLongFieldName->fldtype == 'double') {
01219             $sValue = str_replace( ',', '.', $sValue );
01220         }
01221 
01222         // isset is REQUIRED here not to use getter
01223         if ( isset( $this->$sLongFieldName ) && is_object( $this->$sLongFieldName ) ) {
01224             $this->$sLongFieldName->setValue( $sValue, $iDataType );
01225         } else {
01226             $this->$sLongFieldName = new oxField( $sValue, $iDataType );
01227         }
01228 
01229     }
01230 
01238     protected function _canFieldBeNull( $sFieldName )
01239     {
01240         $aMetaData = $this->_getAllFields();
01241         foreach ( $aMetaData as $oMetaInfo ) {
01242             if ( strcasecmp( $oMetaInfo->name, $sFieldName ) == 0 ) {
01243                 return !$oMetaInfo->not_null;
01244             }
01245         }
01246         return false;
01247     }
01248 
01256     protected function _getFieldDefaultValue( $sFieldName )
01257     {
01258         $aMetaData = $this->_getAllFields();
01259         foreach ( $aMetaData as $oMetaInfo ) {
01260             if ( strcasecmp( $oMetaInfo->name, $sFieldName ) == 0 ) {
01261                 return $oMetaInfo->default_value;
01262             }
01263         }
01264         return false;
01265     }
01266 
01275     protected function _getUpdateFieldValue( $sFieldName, $oField )
01276     {
01277         $mValue = null;
01278         if ( $oField instanceof oxField ) {
01279             $mValue = $oField->getRawValue();
01280         } elseif ( isset( $oField->value ) ) {
01281             $mValue = $oField->value;
01282         }
01283 
01284         $oDb = oxDb::getDb();
01285         //Check if this field value is null AND it can be null according if not returning default value
01286         if ( ( null === $mValue ) ) {
01287             if ( $this->_canFieldBeNull( $sFieldName ) ) {
01288                 return 'null';
01289             } elseif ( $mValue = $this->_getFieldDefaultValue( $sFieldName ) ) {
01290                 return $oDb->quote( $mValue );
01291             }
01292         }
01293 
01294         return $oDb->quote( $mValue );
01295     }
01296 
01305     protected function _getUpdateFields( $blUseSkipSaveFields = true )
01306     {
01307         $sSql = '';
01308         $blSep  = false;
01309 
01310         foreach ( array_keys( $this->_aFieldNames ) as $sKey ) {
01311             $sLongName = $this->_getFieldLongName( $sKey );
01312             $oField = $this->$sLongName;
01313 
01314 
01315             if ( !$blUseSkipSaveFields || ( $blUseSkipSaveFields && !in_array( strtolower( $sKey ), $this->_aSkipSaveFields ) ) ) {
01316                 $sSql .= (( $blSep) ? ',' : '' ) . $sKey . ' = ' . $this->_getUpdateFieldValue( $sKey, $oField );
01317                 $blSep = true;
01318             }
01319         }
01320 
01321         return $sSql;
01322     }
01323 
01333     protected function _update()
01334     {
01335         //do not allow derived item update
01336         if ( !$this->allowDerivedUpdate() ) {
01337             return false;
01338         }
01339 
01340 
01341         if ( !$this->getId() ) {
01345             $oEx = oxNew( 'oxObjectException' );
01346             $oEx->setMessage( 'EXCEPTION_OBJECT_OXIDNOTSET' );
01347             $oEx->setObject($this);
01348             throw $oEx;
01349         }
01350 
01351         $sIDKey = oxRegistry::getUtils()->getArrFldName( $this->_sCoreTable . '.oxid' );
01352         $this->$sIDKey = new oxField($this->getId(), oxField::T_RAW);
01353         $oDb = oxDb::getDb();
01354 
01355         $sUpdate= "update {$this->_sCoreTable} set " . $this->_getUpdateFields()
01356                  ." where {$this->_sCoreTable}.oxid = " . $oDb->quote( $this->getId() );
01357 
01358         //trigger event
01359         $this->beforeUpdate();
01360 
01361         $blRet = (bool) $oDb->execute( $sUpdate );
01362 
01363         return $blRet;
01364     }
01365 
01373     protected function _insert()
01374     {
01375 
01376         $oDb      = oxDb::getDb( oxDb::FETCH_MODE_ASSOC );
01377         $myConfig = $this->getConfig();
01378         $myUtils  = oxRegistry::getUtils();
01379 
01380         // let's get a new ID
01381         if ( !$this->getId()) {
01382             $this->setId();
01383         }
01384 
01385         $sIDKey = $myUtils->getArrFldName( $this->_sCoreTable . '.oxid' );
01386         $this->$sIDKey = new oxField( $this->getId(), oxField::T_RAW );
01387         $sInsert = "Insert into {$this->_sCoreTable} set ";
01388 
01389         //setting oxshopid
01390         $sShopField = $myUtils->getArrFldName( $this->_sCoreTable . '.oxshopid' );
01391 
01392         if ( isset( $this->$sShopField ) && !$this->$sShopField->value ) {
01393             $this->$sShopField = new oxField( $myConfig->getShopId(), oxField::T_RAW );
01394         }
01395 
01396 
01397         $sInsert .= $this->_getUpdateFields( $this->getUseSkipSaveFields() );
01398 
01399         $blRet = (bool) $oDb->execute( $sInsert );
01400 
01401         return $blRet;
01402     }
01403 
01410     protected function _isDisabledFieldCache()
01411     {
01412         $sClass = get_class( $this );
01413         if ( isset( self::$_blDisableFieldCaching[$sClass] ) && self::$_blDisableFieldCaching[$sClass] ) {
01414             return true;
01415         }
01416 
01417         return false;
01418     }
01419 
01425     public function isOx()
01426     {
01427         $sOxId = $this->getId();
01428         if ( $sOxId[0] == 'o' && $sOxId[1] == 'x' ) {
01429             return true;
01430         }
01431         return false;
01432     }
01433 
01439     public function isReadOnly()
01440     {
01441         return $this->_blReadOnly;
01442     }
01443 
01451     public function setReadOnly( $blReadOnly )
01452     {
01453         $this->_blReadOnly = $blReadOnly;
01454     }
01455 
01461     public function getFieldNames()
01462     {
01463         return array_keys( $this->_aFieldNames );
01464     }
01465 
01473     public function addFieldName( $sName )
01474     {
01475         //preparation
01476         $sName = strtolower( $sName );
01477         $this->_aFieldNames[$sName] = 0;
01478     }
01479 
01480 
01486     public function getLanguage()
01487     {
01488         return -1;
01489     }
01490 
01491 }