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 
00646         //getting at least one field before lazy loading the object
00647         $this->_addField( 'oxid', 0 );
00648         $sSelect = $this->buildSelectString( array( $this->getViewName() . '.oxid' => $sOXID) );
00649         $this->_isLoaded = $this->assignRecord( $sSelect );
00650 
00651 
00652         return $this->_isLoaded;
00653     }
00654 
00660     public function isLoaded()
00661     {
00662         return $this->_isLoaded;
00663     }
00664 
00672     public function buildSelectString( $aWhere = null)
00673     {
00674         $oDB = oxDb::getDb();
00675 
00676         $sGet = $this->getSelectFields();
00677         $sSelect = "select $sGet from " . $this->getViewName() . ' where 1 ';
00678 
00679         if ( $aWhere) {
00680             reset($aWhere);
00681             while (list($name, $value) = each($aWhere)) {
00682                 $sSelect .=  ' and ' . $name . ' = '.$oDB->quote($value);
00683             }
00684         }
00685 
00686         // add active shop
00687 
00688         return $sSelect;
00689     }
00690 
00698     public function assignRecord( $sSelect )
00699     {
00700         $blRet = false;
00701 
00702         $rs = oxDb::getDb( oxDb::FETCH_MODE_ASSOC )->select( $sSelect );
00703 
00704         if ($rs != false && $rs->recordCount() > 0) {
00705             $blRet = true;
00706             $this->assign( $rs->fields);
00707         }
00708 
00709         return $blRet;
00710     }
00711 
00719     public function getFieldData( $sFieldName )
00720     {
00721         $sLongFieldName = $this->_getFieldLongName( $sFieldName );
00722             return $this->$sLongFieldName->value;
00723     }
00724 
00732     public function getSelectFields( $blForceCoreTableUsage = null )
00733     {
00734         $aSelectFields = array();
00735 
00736         $sViewName = $this->getViewName( $blForceCoreTableUsage );
00737 
00738         foreach ( $this->_aFieldNames as $sKey => $sField ) {
00739             if ( $sViewName ) {
00740                 $aSelectFields[] = "`$sViewName`.`$sKey`";
00741             } else {
00742                 $aSelectFields[] = ".`$sKey`";
00743             }
00744 
00745         }
00746 
00747         $sSelectFields = join( ', ', $aSelectFields );
00748         return $sSelectFields;
00749     }
00750 
00758     public function delete( $sOXID = null)
00759     {
00760         if ( !$sOXID ) {
00761             $sOXID = $this->getId();
00762 
00763             //do not allow derived deletion
00764             if ( !$this->allowDerivedDelete() ) {
00765                 return false;
00766             }
00767         }
00768 
00769         if ( !$sOXID ) {
00770             return false;
00771         }
00772 
00773 
00774         $oDB = oxDb::getDb( oxDb::FETCH_MODE_ASSOC );
00775         $sDelete = "delete from $this->_sCoreTable where oxid = " . $oDB->quote( $sOXID );
00776         $oDB->execute( $sDelete );
00777         if ( $blDelete = ( bool ) $oDB->affected_Rows() ) {
00778             $this->onChange( ACTION_DELETE, $sOXID );
00779         }
00780 
00781         return $blDelete;
00782     }
00783 
00784 
00790     public function save()
00791     {
00792         if ( !is_array( $this->_aFieldNames ) ) {
00793             return false;
00794         }
00795 
00796         // #739A - should be executed here because of date/time formatting feature
00797         if ( $this->isAdmin() && !$this->getConfig()->getConfigParam( 'blSkipFormatConversion' ) ) {
00798             foreach ($this->_aFieldNames as $sName => $sVal) {
00799                 $sLongName = $this->_getFieldLongName($sName);
00800                 if ( isset($this->$sLongName->fldtype) && $this->$sLongName->fldtype == 'datetime' ) {
00801                     oxRegistry::get('oxUtilsDate')->convertDBDateTime( $this->$sLongName, true );
00802                 } elseif ( isset($this->$sLongName->fldtype) && $this->$sLongName->fldtype == 'timestamp' ) {
00803                     oxRegistry::get('oxUtilsDate')->convertDBTimestamp( $this->$sLongName, true );
00804                 } elseif ( isset($this->$sLongName->fldtype) && $this->$sLongName->fldtype == 'date' ) {
00805                     oxRegistry::get('oxUtilsDate')->convertDBDate( $this->$sLongName, true );
00806                 }
00807             }
00808         }
00809         if ( $this->exists() ) {
00810             //do not allow derived update
00811             if ( !$this->allowDerivedUpdate() ) {
00812                 return false;
00813             }
00814 
00815             $blRet = $this->_update();
00816             $sAction = ACTION_UPDATE;
00817         } else {
00818             $blRet = $this->_insert();
00819             $sAction = ACTION_INSERT;
00820         }
00821 
00822         $this->onChange($sAction);
00823 
00824         if ( $blRet ) {
00825             return $this->getId();
00826         } else {
00827             return false;
00828         }
00829     }
00830 
00836     public function allowDerivedUpdate()
00837     {
00838         return !$this->isDerived();
00839     }
00840 
00846     public function allowDerivedDelete()
00847     {
00848         return !$this->isDerived();
00849     }
00850 
00858     public function exists( $sOXID = null)
00859     {
00860         if ( !$sOXID ) {
00861             $sOXID = $this->getId();
00862         }
00863         if ( !$sOXID ) {
00864             return false;
00865         }
00866 
00867         $sViewName = $this->getCoreTableName();
00868         $oDb = oxDb::getDb( oxDb::FETCH_MODE_ASSOC );
00869         $sSelect= "select {$this->_sExistKey} from {$sViewName} where {$this->_sExistKey} = " . $oDb->quote( $sOXID );
00870 
00871         return ( bool ) $oDb->getOne( $sSelect, false, false );
00872     }
00873 
00881     public function getSqlActiveSnippet( $blForceCoreTable = null )
00882     {
00883         $sQ = '';
00884         $sTable = $this->getViewName($blForceCoreTable);
00885 
00886         // has 'active' field ?
00887         if ( isset( $this->_aFieldNames['oxactive'] ) ) {
00888             $sQ = " $sTable.oxactive = 1 ";
00889         }
00890 
00891         // has 'activefrom'/'activeto' fields ?
00892         if ( isset( $this->_aFieldNames['oxactivefrom'] ) && isset( $this->_aFieldNames['oxactiveto'] ) ) {
00893 
00894             $sDate = date( 'Y-m-d H:i:s', oxRegistry::get('oxUtilsDate')->getTime() );
00895 
00896             $sQ = $sQ ? " $sQ or " : '';
00897             $sQ = " ( $sQ ( $sTable.oxactivefrom < '$sDate' and $sTable.oxactiveto > '$sDate' ) ) ";
00898         }
00899 
00900         return $sQ;
00901     }
00902 
00911     public function beforeUpdate( $sOXID = null )
00912     {
00913     }
00914 
00925     public function onChange( $iAction = null, $sOXID = null )
00926     {
00927     }
00928 
00929 
00935     public function setInList()
00936     {
00937         $this->_blIsInList = true;
00938     }
00939 
00945     protected function _isInList()
00946     {
00947         return $this->_blIsInList;
00948     }
00949 
00958     protected function _getObjectViewName( $sTable, $sShopID = null )
00959     {
00960         return getViewName( $sTable, -1, $sShopID);
00961     }
00962 
00963 
00974     protected function _getTableFields($sTable, $blReturnSimple = false )
00975     {
00976         $myUtils = oxRegistry::getUtils();
00977 
00978         $sCacheKey   = $sTable . '_allfields_' . $blReturnSimple;
00979         $aMetaFields = $myUtils->fromFileCache( $sCacheKey );
00980 
00981         if ( $aMetaFields ) {
00982             return $aMetaFields;
00983         }
00984 
00985         $aMetaFields = oxDb::getInstance()->getTableDescription( $sTable );
00986 
00987         if ( !$blReturnSimple ) {
00988             $myUtils->toFileCache( $sCacheKey, $aMetaFields );
00989             return $aMetaFields;
00990         }
00991 
00992         //returning simple array
00993         $aRet = array();
00994         if (is_array($aMetaFields)) {
00995             foreach ( $aMetaFields as $oVal ) {
00996                 $aRet[strtolower( $oVal->name )] = 0;
00997             }
00998         }
00999 
01000         $myUtils->toFileCache( $sCacheKey, $aRet);
01001 
01002         return $aRet;
01003     }
01004 
01016     protected function _getAllFields($blReturnSimple = false )
01017     {
01018         if (!$this->_sCoreTable) {
01019             return array();
01020         }
01021         return $this->_getTableFields($this->_sCoreTable, $blReturnSimple);
01022     }
01023 
01032     protected function _initDataStructure($blForceFullStructure = false )
01033     {
01034         $myUtils = oxRegistry::getUtils();
01035 
01036         //get field names from cache
01037         $aFieldNames = null;
01038         $sFullCacheKey = 'fieldnames_' . $this->_sCoreTable . '_' . $this->_sCacheKey;
01039         if ($this->_sCacheKey && !$this->_isDisabledFieldCache()) {
01040             $aFieldNames = $myUtils->fromFileCache( $sFullCacheKey );
01041         }
01042 
01043         if (!$aFieldNames) {
01044             $aFieldNames = $this->_getNonCachedFieldNames( $blForceFullStructure );
01045             if ($this->_sCacheKey && !$this->_isDisabledFieldCache()) {
01046                 $myUtils->toFileCache( $sFullCacheKey, $aFieldNames );
01047             }
01048         }
01049 
01050         if ( $aFieldNames !== false ) {
01051             foreach ( $aFieldNames as $sField => $sStatus ) {
01052                 $this->_addField( $sField, $sStatus );
01053             }
01054         }
01055     }
01056 
01068     protected function _getNonCachedFieldNames( $blForceFullStructure = false )
01069     {
01070         //T2008-02-22
01071         //so if this method is executed on cached version we see it when profiling
01072         startProfile('!__CACHABLE__!');
01073 
01074         //case 1. (admin)
01075         if ($this->isAdmin()) {
01076             $aMetaFields = $this->_getAllFields();
01077             foreach ( $aMetaFields as $oField ) {
01078                 if ( $oField->max_length == -1 ) {
01079                     $oField->max_length = 10;      // double or float
01080                 }
01081 
01082                 if ( $oField->type == 'datetime' ) {
01083                     $oField->max_length = 20;
01084                 }
01085 
01086                 $this->_addField( $oField->name, $this->_getFieldStatus($oField->name), $oField->type, $oField->max_length );
01087             }
01088             stopProfile('!__CACHABLE__!');
01089             return false;
01090         }
01091 
01092         //case 2. (just get all fields)
01093         if ( $blForceFullStructure || !$this->_blUseLazyLoading ) {
01094             $aMetaFields = $this->_getAllFields(true);
01095             /*
01096             foreach ( $aMetaFields as $sFieldName => $sVal) {
01097                 $this->_addField( $sFieldName, $this->_getFieldStatus($sFieldName));
01098             }*/
01099             stopProfile('!__CACHABLE__!');
01100             return $aMetaFields;
01101         }
01102 
01103         //case 3. (get only oxid field, so we can fetch the rest of the fields over lazy loading mechanism)
01104         stopProfile('!__CACHABLE__!');
01105         return array('oxid' => 0);
01106     }
01107 
01116     protected function _getFieldStatus( $sFieldName )
01117     {
01118         return 0;
01119     }
01120 
01131     protected function _addField($sName, $iStatus, $sType = null, $sLength = null )
01132     {
01133         //preparation
01134         $sName = strtolower( $sName );
01135 
01136         //adding field names element
01137         $this->_aFieldNames[$sName] = $iStatus;
01138 
01139         //already set?
01140         $sLongName = $this->_getFieldLongName( $sName );
01141         if ( isset($this->$sLongName) ) {
01142             return;
01143         }
01144 
01145         //defining the field
01146         $oField = false;
01147 
01148         if ( isset( $sType ) ) {
01149             $oField = new oxField();
01150             $oField->fldtype = $sType;
01151             //T2008-01-29
01152             //can't clone as the fields are objects and are not fully cloned
01153             $this->_blIsSimplyClonable = false;
01154         }
01155 
01156         if ( isset( $sLength ) ) {
01157             if ( !$oField ) {
01158                 $oField = new oxField();
01159             }
01160             $oField->fldmax_length = $sLength;
01161             $this->_blIsSimplyClonable = false;
01162         }
01163 
01164         $this->$sLongName = $oField;
01165     }
01166 
01174     protected function _getFieldLongName( $sFieldName )
01175     {
01176         //trying to avoid strpos call as often as possible
01177         if ( $sFieldName[2] == $this->_sCoreTable[2] && strpos( $sFieldName, $this->_sCoreTable . '__' ) === 0 ) {
01178             return $sFieldName;
01179         }
01180 
01181         return $this->_sCoreTable . '__' . strtolower( $sFieldName );
01182     }
01183 
01193     protected function _setFieldData( $sFieldName, $sValue, $iDataType = oxField::T_TEXT )
01194     {
01195 
01196         $sLongFieldName = $this->_getFieldLongName( $sFieldName);
01197         //$sLongFieldName = $this->_sCoreTable . "__" . strtolower($sFieldName);
01198 
01199         //T2008-03-14
01200         //doing this because in lazy loaded lists on first load it is harmful to have initialised fields but not yet set
01201         //situation: only first article is loaded fully for "select oxid from oxarticles"
01202         /*
01203         if ($this->_blUseLazyLoading && !isset($this->$sLongFieldName))
01204             return;*/
01205 
01206         //in non lazy loading case we just add a field and do not care about it more
01207         if (!$this->_blUseLazyLoading && !isset( $this->$sLongFieldName )) {
01208             $aFields = $this->_getAllFields(true);
01209             if ( isset( $aFields[strtolower( $sFieldName )] ) ) {
01210                 $this->_addField( $sFieldName, $this->_getFieldStatus( $sFieldName ) );
01211             }
01212         }
01213         // if we have a double field we replace "," with "." in case somebody enters it in european format
01214         if (isset($this->$sLongFieldName) && isset( $this->$sLongFieldName->fldtype ) && $this->$sLongFieldName->fldtype == 'double') {
01215             $sValue = str_replace( ',', '.', $sValue );
01216         }
01217 
01218         // isset is REQUIRED here not to use getter
01219         if ( isset( $this->$sLongFieldName ) && is_object( $this->$sLongFieldName ) ) {
01220             $this->$sLongFieldName->setValue( $sValue, $iDataType );
01221         } else {
01222             $this->$sLongFieldName = new oxField( $sValue, $iDataType );
01223         }
01224 
01225     }
01226 
01234     protected function _canFieldBeNull( $sFieldName )
01235     {
01236         $aMetaData = $this->_getAllFields();
01237         foreach ( $aMetaData as $oMetaInfo ) {
01238             if ( strcasecmp( $oMetaInfo->name, $sFieldName ) == 0 ) {
01239                 return !$oMetaInfo->not_null;
01240             }
01241         }
01242         return false;
01243     }
01244 
01252     protected function _getFieldDefaultValue( $sFieldName )
01253     {
01254         $aMetaData = $this->_getAllFields();
01255         foreach ( $aMetaData as $oMetaInfo ) {
01256             if ( strcasecmp( $oMetaInfo->name, $sFieldName ) == 0 ) {
01257                 return $oMetaInfo->default_value;
01258             }
01259         }
01260         return false;
01261     }
01262 
01271     protected function _getUpdateFieldValue( $sFieldName, $oField )
01272     {
01273         $mValue = null;
01274         if ( $oField instanceof oxField ) {
01275             $mValue = $oField->getRawValue();
01276         } elseif ( isset( $oField->value ) ) {
01277             $mValue = $oField->value;
01278         }
01279 
01280         $oDb = oxDb::getDb();
01281         //Check if this field value is null AND it can be null according if not returning default value
01282         if ( ( null === $mValue ) ) {
01283             if ( $this->_canFieldBeNull( $sFieldName ) ) {
01284                 return 'null';
01285             } elseif ( $mValue = $this->_getFieldDefaultValue( $sFieldName ) ) {
01286                 return $oDb->quote( $mValue );
01287             }
01288         }
01289 
01290         return $oDb->quote( $mValue );
01291     }
01292 
01301     protected function _getUpdateFields( $blUseSkipSaveFields = true )
01302     {
01303         $sSql = '';
01304         $blSep  = false;
01305 
01306         foreach ( array_keys( $this->_aFieldNames ) as $sKey ) {
01307             $sLongName = $this->_getFieldLongName( $sKey );
01308             $oField = $this->$sLongName;
01309 
01310 
01311             if ( !$blUseSkipSaveFields || ( $blUseSkipSaveFields && !in_array( strtolower( $sKey ), $this->_aSkipSaveFields ) ) ) {
01312                 $sSql .= (( $blSep) ? ',' : '' ) . $sKey . ' = ' . $this->_getUpdateFieldValue( $sKey, $oField );
01313                 $blSep = true;
01314             }
01315         }
01316 
01317         return $sSql;
01318     }
01319 
01329     protected function _update()
01330     {
01331         //do not allow derived item update
01332         if ( !$this->allowDerivedUpdate() ) {
01333             return false;
01334         }
01335 
01336 
01337         if ( !$this->getId() ) {
01341             $oEx = oxNew( 'oxObjectException' );
01342             $oEx->setMessage( 'EXCEPTION_OBJECT_OXIDNOTSET' );
01343             $oEx->setObject($this);
01344             throw $oEx;
01345         }
01346 
01347         $sIDKey = oxRegistry::getUtils()->getArrFldName( $this->_sCoreTable . '.oxid' );
01348         $this->$sIDKey = new oxField($this->getId(), oxField::T_RAW);
01349         $oDb = oxDb::getDb();
01350 
01351         $sUpdate= "update {$this->_sCoreTable} set " . $this->_getUpdateFields()
01352                  ." where {$this->_sCoreTable}.oxid = " . $oDb->quote( $this->getId() );
01353 
01354         //trigger event
01355         $this->beforeUpdate();
01356 
01357         $blRet = (bool) $oDb->execute( $sUpdate );
01358 
01359         return $blRet;
01360     }
01361 
01369     protected function _insert()
01370     {
01371 
01372         $oDb      = oxDb::getDb( oxDb::FETCH_MODE_ASSOC );
01373         $myConfig = $this->getConfig();
01374         $myUtils  = oxRegistry::getUtils();
01375 
01376         // let's get a new ID
01377         if ( !$this->getId()) {
01378             $this->setId();
01379         }
01380 
01381         $sIDKey = $myUtils->getArrFldName( $this->_sCoreTable . '.oxid' );
01382         $this->$sIDKey = new oxField( $this->getId(), oxField::T_RAW );
01383         $sInsert = "Insert into {$this->_sCoreTable} set ";
01384 
01385         //setting oxshopid
01386         $sShopField = $myUtils->getArrFldName( $this->_sCoreTable . '.oxshopid' );
01387 
01388         if ( isset( $this->$sShopField ) && !$this->$sShopField->value ) {
01389             $this->$sShopField = new oxField( $myConfig->getShopId(), oxField::T_RAW );
01390         }
01391 
01392 
01393         $sInsert .= $this->_getUpdateFields( $this->getUseSkipSaveFields() );
01394 
01395         $blRet = (bool) $oDb->execute( $sInsert );
01396 
01397         return $blRet;
01398     }
01399 
01406     protected function _isDisabledFieldCache()
01407     {
01408         $sClass = get_class( $this );
01409         if ( isset( self::$_blDisableFieldCaching[$sClass] ) && self::$_blDisableFieldCaching[$sClass] ) {
01410             return true;
01411         }
01412 
01413         return false;
01414     }
01415 
01421     public function isOx()
01422     {
01423         $sOxId = $this->getId();
01424         if ( $sOxId[0] == 'o' && $sOxId[1] == 'x' ) {
01425             return true;
01426         }
01427         return false;
01428     }
01429 
01435     public function isReadOnly()
01436     {
01437         return $this->_blReadOnly;
01438     }
01439 
01447     public function setReadOnly( $blReadOnly )
01448     {
01449         $this->_blReadOnly = $blReadOnly;
01450     }
01451 
01457     public function getFieldNames()
01458     {
01459         return array_keys( $this->_aFieldNames );
01460     }
01461 
01469     public function addFieldName( $sName )
01470     {
01471         //preparation
01472         $sName = strtolower( $sName );
01473         $this->_aFieldNames[$sName] = 0;
01474     }
01475 
01476 
01482     public function getLanguage()
01483     {
01484         return -1;
01485     }
01486 
01487 }