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 
00085 
00091     protected $_blUseSkipSaveFields = true;
00092 
00097     protected $_sExistKey = "oxid";
00098 
00105     protected $_blIsDerived = null;
00106 
00116     protected static $_blDisableFieldCaching = array();
00117 
00123     protected $_blIsSeoObject = false;
00124 
00130     protected $_blReadOnly = false;
00131 
00137     protected $_blIsInList = false;
00138 
00144     protected $_isLoaded = false;
00145 
00151     protected $_aInnerLazyCache = null;
00152 
00158     protected $_blEmployMultilanguage = false;
00159 
00160 
00166     public function getUseSkipSaveFields()
00167     {
00168         return $this->_blUseSkipSaveFields;
00169     }
00170 
00178     public function setUseSkipSaveFields( $blUseSkipSaveFields )
00179     {
00180         $this->_blUseSkipSaveFields = $blUseSkipSaveFields;
00181     }
00182 
00186     public function __construct()
00187     {
00188         // set active shop
00189         $myConfig = $this->getConfig();
00190         $this->_sCacheKey = $this->getViewName();
00191 
00192 
00193         if ( $this->_blUseLazyLoading ) {
00194             $this->_sCacheKey .= $myConfig->getActiveView()->getClassName();
00195         } else {
00196             $this->_sCacheKey .= "allviews";
00197         }
00198 
00199         //do not cache for admin?
00200         if ( $this->isAdmin() ) {
00201             $this->_sCacheKey = null;
00202         }
00203 
00204         $this->setShopId( $myConfig->getShopId() );
00205     }
00206 
00215     public function __set( $sName, $sValue )
00216     {
00217         $this->$sName = $sValue;
00218         if ( $this->_blUseLazyLoading && strpos( $sName, $this->_sCoreTable . "__" ) === 0 ) {
00219             $sFieldName = str_replace( $this->_sCoreTable . "__", '', $sName );
00220             if ( $sFieldName != 'oxnid' && ( !isset( $this->_aFieldNames[$sFieldName] ) || !$this->_aFieldNames[$sFieldName] ) ) {
00221                 $aAllFields = $this->_getAllFields(true);
00222                 if ( isset( $aAllFields[strtolower($sFieldName)] ) ) {
00223                     $iFieldStatus = $this->_getFieldStatus( $sFieldName );
00224                     $this->_addField( $sFieldName, $iFieldStatus );
00225                 }
00226             }
00227         }
00228     }
00229 
00237     public function __get( $sName )
00238     {
00239         switch ( $sName ) {
00240             case 'blIsDerived':
00241                 return $this->isDerived();
00242                 break;
00243             case 'sOXID':
00244                 return $this->getId();
00245                 break;
00246             case 'blReadOnly':
00247                 return $this->isReadOnly();
00248                 break;
00249         }
00250 
00251         // implementing lazy loading fields
00252         // This part of the code is slow and normally is called before field cache is built.
00253         // Make sure it is not called after first page is loaded and cache data is fully built.
00254         if ( $this->_blUseLazyLoading && stripos( $sName, $this->_sCoreTable . "__" ) === 0 ) {
00255 
00256             if ( $this->getId() ) {
00257 
00258                 //lazy load it
00259                 $sFieldName      = str_replace( $this->_sCoreTable . "__", '', $sName );
00260                 $sCacheFieldName = strtoupper( $sFieldName );
00261 
00262                 $iFieldStatus = $this->_getFieldStatus( $sFieldName );
00263                 $sViewName    = $this->getViewName();
00264                 $sId = $this->getId();
00265 
00266                 try {
00267                     if ( $this->_aInnerLazyCache === null ) {
00268 
00269                         $oDb = oxDb::getDb( oxDb::FETCH_MODE_ASSOC );
00270                         $sQ = "SELECT * FROM " . $sViewName . " WHERE `oxid` = " . $oDb->quote( $sId );
00271                         $rs = $oDb->select( $sQ );
00272                         if ( $rs && $rs->RecordCount() ) {
00273                             $this->_aInnerLazyCache = array_change_key_case( $rs->fields, CASE_UPPER );
00274                             if ( array_key_exists( $sCacheFieldName, $this->_aInnerLazyCache ) ) {
00275                                 $sFieldValue = $this->_aInnerLazyCache[$sCacheFieldName];
00276                             } else {
00277                                 return null;
00278                             }
00279                         } else {
00280                             return null;
00281                         }
00282                     } elseif ( array_key_exists( $sCacheFieldName, $this->_aInnerLazyCache ) ) {
00283                         $sFieldValue = $this->_aInnerLazyCache[$sCacheFieldName];
00284                     } else {
00285                         return null;
00286                     }
00287 
00288                     $this->_addField( $sFieldName, $iFieldStatus );
00289                     $this->_setFieldData( $sFieldName, $sFieldValue );
00290 
00291                     //save names to cache for next loading
00292                     if ($this->_sCacheKey) {
00293                         $myUtils = oxRegistry::getUtils();
00294                         $sCacheKey = 'fieldnames_' . $this->_sCoreTable . "_" . $this->_sCacheKey;
00295                         $aFieldNames = $myUtils->fromFileCache( $sCacheKey );
00296                         $aFieldNames[$sFieldName] = $iFieldStatus;
00297                         $myUtils->toFileCache( $sCacheKey, $aFieldNames );
00298                     }
00299                 } catch ( Exception $e ) {
00300                     return null;
00301                 }
00302 
00303                 //do not use field cache for this page
00304                 //as if we use it for lists then objects are loaded empty instead of lazy loading.
00305                 self::$_blDisableFieldCaching[get_class( $this )] = true;
00306             }
00307 
00308             oxUtilsObject::getInstance()->resetInstanceCache(get_class($this));
00309         }
00310 
00311         //returns stdClass implementing __toString() method due to uknown scenario where this var should be used.
00312         if (!isset( $this->$sName ) ) {
00313             $this->$sName = null;
00314         }
00315 
00316         return $this->$sName;
00317     }
00318 
00326     public function __isset($mVar)
00327     {
00328         return isset($this->$mVar);
00329     }
00330 
00336     public function __clone()
00337     {
00338         if (!$this->_blIsSimplyClonable) {
00339             foreach ( $this->_aFieldNames as $sField => $sVal ) {
00340                 $sLongName = $this->_getFieldLongName( $sField );
00341                 if ( is_object($this->$sLongName)) {
00342                     $this->$sLongName = clone $this->$sLongName;
00343                 }
00344             }
00345         }
00346     }
00347 
00355     public function oxClone($oObject)
00356     {
00357         $aClasVars = get_object_vars( $oObject);
00358         while (list($name, $value) = each($aClasVars)) {
00359             if ( is_object( $oObject->$name ) ) {
00360                 $this->$name = clone $oObject->$name;
00361             } else {
00362                 $this->$name = $oObject->$name;
00363             }
00364         }
00365     }
00366 
00375     public function init( $sTableName = null, $blForceAllFields = false)
00376     {
00377 
00378         if ( !$sTableName ) {
00379             $sTableName = $this->_sCoreTable;
00380         } else {
00381             $this->_sCoreTable = $sTableName;
00382         }
00383 
00384         // reset view table
00385         $this->_sViewTable = false;
00386 
00387         if ( count( $this->_aFieldNames ) <= 1 ) {
00388             $this->_initDataStructure( $blForceAllFields );
00389         }
00390     }
00391 
00399     public function assign( $dbRecord )
00400     {
00401         if ( !is_array( $dbRecord ) ) {
00402             return;
00403         }
00404 
00405 
00406         reset($dbRecord );
00407         while ( list( $sName, $sValue ) = each( $dbRecord ) ) {
00408 
00409             // patch for IIS
00410             //TODO: test it on IIS do we still need it
00411             //if( is_array($value) && count( $value) == 1)
00412             //    $value = current( $value);
00413 
00414             $this->_setFieldData( $sName, $sValue );
00415         }
00416 
00417         $sOxidField = $this->_getFieldLongName( 'oxid' );
00418         $this->_sOXID = $this->$sOxidField->value;
00419 
00420     }
00421 
00427     public function getClassName()
00428     {
00429         return $this->_sClassName;
00430     }
00431 
00437     public function getCoreTableName()
00438     {
00439         return $this->_sCoreTable;
00440     }
00441 
00447     public function getId()
00448     {
00449         return $this->_sOXID;
00450     }
00451 
00459     public function setId($sOXID = null)
00460     {
00461         if ( $sOXID ) {
00462             $this->_sOXID = $sOXID;
00463         } else {
00464             $this->_sOXID = oxUtilsObject::getInstance()->generateUID();
00465         }
00466 
00467         $sIdVarName = $this->_sCoreTable . "__oxid";
00468         $this->$sIdVarName = new oxField($this->_sOXID, oxField::T_RAW);
00469 
00470         return $this->_sOXID;
00471     }
00472 
00480     public function setShopId($iShopId)
00481     {
00482         $this->_iShopId = $iShopId;
00483     }
00484 
00490     public function getShopId()
00491     {
00492         return $this->_iShopId;
00493     }
00494 
00502     public function getViewName($blForceCoreTableUsage = null)
00503     {
00504         if (!$this->_sViewTable || ($blForceCoreTableUsage !== null)) {
00505             if ( $blForceCoreTableUsage === true ) {
00506                 return $this->_sCoreTable;
00507             }
00508 
00509 
00510             if ( ( $blForceCoreTableUsage !== null ) && $blForceCoreTableUsage ) {
00511                 $iShopId = -1;
00512             } else {
00513                 $iShopId = oxRegistry::getConfig()->getShopId();
00514             }
00515 
00516 
00517             $sViewName = getViewName( $this->_sCoreTable, $this->_blEmployMultilanguage == false ? -1 : $this->getLanguage(), $iShopId );
00518             if ( $blForceCoreTableUsage !== null ) {
00519                 return $sViewName;
00520             }
00521             $this->_sViewTable = $sViewName;
00522         }
00523         return $this->_sViewTable;
00524     }
00525 
00534     public function modifyCacheKey( $sCacheKey, $blOverride = false )
00535     {
00536         if ( $blOverride ) {
00537             $this->_sCacheKey = $sCacheKey;
00538         } else {
00539             $this->_sCacheKey .= $sCacheKey;
00540         }
00541     }
00542 
00548     public function disableLazyLoading()
00549     {
00550         $this->_blUseLazyLoading = false;
00551         $this->_initDataStructure(true);
00552     }
00553 
00554 
00560     public function isDerived()
00561     {
00562 
00563         return $this->_blIsDerived;
00564     }
00565 
00573     public function setIsDerived($blVal)
00574     {
00575         $this->_blIsDerived = $blVal;
00576     }
00577 
00584     public function isMultilang()
00585     {
00586         return false;
00587     }
00588 
00598     public function load( $sOXID )
00599     {
00600         $blExistingOldForceCoreTable = $this->_blForceCoreTableUsage;
00601 
00602         $this->_blForceCoreTableUsage = true;
00603 
00604         //getting at least one field before lazy loading the object
00605         $this->_addField('oxid', 0);
00606         $sSelect = $this->buildSelectString( array( $this->getViewName().".oxid" => $sOXID));
00607         $this->_isLoaded = $this->assignRecord( $sSelect );
00608 
00609         $this->_blForceCoreTableUsage = $blExistingOldForceCoreTable;
00610 
00611         return $this->_isLoaded;
00612     }
00613 
00619     public function isLoaded()
00620     {
00621         return $this->_isLoaded;
00622     }
00623 
00631     public function buildSelectString( $aWhere = null)
00632     {
00633         $oDB = oxDb::getDb();
00634         $myUtils = oxRegistry::getUtils();
00635 
00636         $sGet = $this->getSelectFields();
00637         $sSelect = "select $sGet from " . $this->getViewName() . " where 1 ";
00638 
00639         if ( $aWhere) {
00640             reset($aWhere);
00641             while (list($name, $value) = each($aWhere)) {
00642                 $sSelect .=  " and " . $name.' = '.$oDB->quote($value);
00643             }
00644         }
00645 
00646         // add active shop
00647 
00648         return $sSelect;
00649     }
00650 
00658     public function assignRecord( $sSelect )
00659     {
00660         $blRet = false;
00661 
00662         $rs = oxDb::getDb( oxDb::FETCH_MODE_ASSOC )->select( $sSelect );
00663 
00664         if ($rs != false && $rs->recordCount() > 0) {
00665             $blRet = true;
00666             $this->assign( $rs->fields);
00667         }
00668 
00669         return $blRet;
00670     }
00671 
00679     public function getFieldData( $sFieldName )
00680     {
00681         $sLongFieldName = $this->_getFieldLongName( $sFieldName );
00682             return $this->$sLongFieldName->value;
00683     }
00684 
00692     public function getSelectFields( $blForceCoreTableUsage = null )
00693     {
00694         $aSelectFields = array();
00695 
00696         $sViewName = $this->getViewName( $blForceCoreTableUsage );
00697 
00698         foreach ( $this->_aFieldNames as $sKey => $sField ) {
00699             if ( $sViewName ) {
00700                 $aSelectFields[] = "`$sViewName`.`$sKey`";
00701             } else {
00702                 $aSelectFields[] = ".`$sKey`";
00703             }
00704 
00705         }
00706 
00707         $sSelectFields = join( ", ", $aSelectFields );
00708         return $sSelectFields;
00709     }
00710 
00718     public function delete( $sOXID = null)
00719     {
00720         if ( !$sOXID ) {
00721             $sOXID = $this->getId();
00722 
00723             //do not allow derived deletion
00724             if ( !$this->allowDerivedDelete() ) {
00725                 return false;
00726             }
00727         }
00728 
00729         if ( !$sOXID ) {
00730             return false;
00731         }
00732 
00733 
00734         $oDB = oxDb::getDb( oxDb::FETCH_MODE_ASSOC );
00735         $sDelete = "delete from $this->_sCoreTable where oxid = ".$oDB->quote( $sOXID );
00736         $rs = $oDB->execute( $sDelete );
00737         if ( $blDelete = ( bool ) $oDB->affected_Rows() ) {
00738             $this->onChange(ACTION_DELETE, $sOXID);
00739         }
00740 
00741         return $blDelete;
00742     }
00743 
00744 
00750     public function save()
00751     {
00752         if ( !is_array( $this->_aFieldNames ) ) {
00753             return false;
00754         }
00755 
00756         $blRet = false;
00757 
00758         // #739A - should be executed here because of date/time formatting feature
00759         if ( $this->isAdmin() && !$this->getConfig()->getConfigParam( 'blSkipFormatConversion' ) ) {
00760             foreach ($this->_aFieldNames as $sName => $sVal) {
00761                 $sLongName = $this->_getFieldLongName($sName);
00762                 if ( isset($this->$sLongName->fldtype) && $this->$sLongName->fldtype == "datetime" ) {
00763                     oxRegistry::get("oxUtilsDate")->convertDBDateTime( $this->$sLongName, true );
00764                 } elseif ( isset($this->$sLongName->fldtype) && $this->$sLongName->fldtype == "timestamp" ) {
00765                     oxRegistry::get("oxUtilsDate")->convertDBTimestamp( $this->$sLongName, true);
00766                 } elseif ( isset($this->$sLongName->fldtype) && $this->$sLongName->fldtype == "date" ) {
00767                     oxRegistry::get("oxUtilsDate")->convertDBDate( $this->$sLongName, true);
00768                 }
00769             }
00770         }
00771         if ( $this->exists() ) {
00772             //do not allow derived update
00773             if ( !$this->allowDerivedUpdate() ) {
00774                 return false;
00775             }
00776 
00777             $blRet = $this->_update();
00778             $sAction = ACTION_UPDATE;
00779         } else {
00780             $blRet = $this->_insert();
00781             $sAction = ACTION_INSERT;
00782         }
00783 
00784         $this->onChange($sAction);
00785 
00786         if ( $blRet ) {
00787             return $this->getId();
00788         } else {
00789             return false;
00790         }
00791     }
00792 
00798     public function allowDerivedUpdate()
00799     {
00800         return !$this->isDerived();
00801     }
00802 
00808     public function allowDerivedDelete()
00809     {
00810         return !$this->isDerived();
00811     }
00812 
00820     public function exists( $sOXID = null)
00821     {
00822         if ( !$sOXID ) {
00823             $sOXID = $this->getId();
00824         }
00825         if ( !$sOXID ) {
00826             return false;
00827         }
00828 
00829         $sViewName = $this->getCoreTableName();
00830         $oDb = oxDb::getDb( oxDb::FETCH_MODE_ASSOC );
00831         $sSelect= "select {$this->_sExistKey} from {$sViewName} where {$this->_sExistKey} = ".$oDb->quote( $sOXID );
00832 
00833         return ( bool ) $oDb->getOne( $sSelect, false, false );
00834     }
00835 
00843     public function getSqlActiveSnippet( $blForceCoreTable = null )
00844     {
00845         $sQ = '';
00846         $sTable = $this->getViewName($blForceCoreTable);
00847 
00848         // has 'active' field ?
00849         if ( isset( $this->_aFieldNames['oxactive'] ) ) {
00850             $sQ = " $sTable.oxactive = 1 ";
00851         }
00852 
00853         // has 'activefrom'/'activeto' fields ?
00854         if ( isset( $this->_aFieldNames['oxactivefrom'] ) && isset( $this->_aFieldNames['oxactiveto'] ) ) {
00855 
00856             $sDate = date( 'Y-m-d H:i:s', oxRegistry::get("oxUtilsDate")->getTime() );
00857 
00858             $sQ = $sQ?" $sQ or ":'';
00859             $sQ = " ( $sQ ( $sTable.oxactivefrom < '$sDate' and $sTable.oxactiveto > '$sDate' ) ) ";
00860         }
00861 
00862         return $sQ;
00863     }
00864 
00873     public function beforeUpdate( $sOXID = null )
00874     {
00875     }
00876 
00887     public function onChange( $iAction = null, $sOXID = null)
00888     {
00889     }
00890 
00891 
00897     public function setInList()
00898     {
00899         $this->_blIsInList = true;
00900     }
00901 
00907     protected function _isInList()
00908     {
00909         return $this->_blIsInList;
00910     }
00911 
00920     protected function _getObjectViewName( $sTable, $sShopID = null)
00921     {
00922         return getViewName( $sTable, -1, $sShopID);
00923     }
00924 
00925 
00936     protected function _getTableFields($sTable, $blReturnSimple = false)
00937     {
00938         $myUtils = oxRegistry::getUtils();
00939 
00940         $sCacheKey   = $sTable . "_allfields_" . $blReturnSimple;
00941         $aMetaFields = $myUtils->fromFileCache( $sCacheKey );
00942 
00943         if ( $aMetaFields ) {
00944             return $aMetaFields;
00945         }
00946 
00947         $aMetaFields = oxDb::getInstance()->getTableDescription( $sTable );
00948 
00949         if ( !$blReturnSimple ) {
00950             $myUtils->toFileCache( $sCacheKey, $aMetaFields );
00951             return $aMetaFields;
00952         }
00953 
00954         //returning simple array
00955         $aRet = array();
00956         if (is_array($aMetaFields)) {
00957             foreach ( $aMetaFields as $oVal ) {
00958                 $aRet[strtolower( $oVal->name )] = 0;
00959             }
00960         }
00961 
00962         $myUtils->toFileCache( $sCacheKey, $aRet);
00963 
00964         return $aRet;
00965     }
00966 
00978     protected function _getAllFields($blReturnSimple = false)
00979     {
00980         if (!$this->_sCoreTable) {
00981             return array();
00982         }
00983         return $this->_getTableFields($this->_sCoreTable, $blReturnSimple);
00984     }
00985 
00994     protected function _initDataStructure($blForceFullStructure = false)
00995     {
00996         $myUtils = oxRegistry::getUtils();
00997 
00998         //get field names from cache
00999         $aFieldNames = null;
01000         $sFullCacheKey = 'fieldnames_' .$this->_sCoreTable . "_" . $this->_sCacheKey;
01001         if ($this->_sCacheKey && !$this->_isDisabledFieldCache()) {
01002             $aFieldNames = $myUtils->fromFileCache($sFullCacheKey);
01003         }
01004 
01005         if (!$aFieldNames) {
01006             $aFieldNames = $this->_getNonCachedFieldNames($blForceFullStructure);
01007             if ($this->_sCacheKey && !$this->_isDisabledFieldCache()) {
01008                 $myUtils->toFileCache($sFullCacheKey, $aFieldNames);
01009             }
01010         }
01011 
01012         if ( $aFieldNames !== false ) {
01013             foreach ( $aFieldNames as $sField => $sStatus ) {
01014                 $this->_addField($sField, $sStatus);
01015             }
01016         }
01017     }
01018 
01030     protected function _getNonCachedFieldNames($blForceFullStructure = false)
01031     {
01032         //T2008-02-22
01033         //so if this method is executed on cached version we see it when profiling
01034         startProfile("!__CACHABLE__!");
01035 
01036         //case 1. (admin)
01037         if ($this->isAdmin()) {
01038             $aMetaFields = $this->_getAllFields();
01039             foreach ( $aMetaFields as $oField ) {
01040                 if ( $oField->max_length == -1 ) {
01041                     $oField->max_length = 10;      // double or float
01042                 }
01043 
01044                 if ( $oField->type == "datetime" ) {
01045                     $oField->max_length = 20;
01046                 }
01047 
01048                 $this->_addField( $oField->name, $this->_getFieldStatus($oField->name), $oField->type, $oField->max_length );
01049             }
01050             stopProfile("!__CACHABLE__!");
01051             return false;
01052         }
01053 
01054         //case 2. (just get all fields)
01055         if ( $blForceFullStructure || !$this->_blUseLazyLoading ) {
01056             $aMetaFields = $this->_getAllFields(true);
01057             /*
01058             foreach ( $aMetaFields as $sFieldName => $sVal) {
01059                 $this->_addField( $sFieldName, $this->_getFieldStatus($sFieldName));
01060             }*/
01061             stopProfile("!__CACHABLE__!");
01062             return $aMetaFields;
01063         }
01064 
01065         //case 3. (get only oxid field, so we can fetch the rest of the fields over lazy loading mechanism)
01066         stopProfile("!__CACHABLE__!");
01067         return array("oxid" => 0);
01068     }
01069 
01078     protected function _getFieldStatus( $sFieldName )
01079     {
01080         return 0;
01081     }
01082 
01093     protected function _addField($sName, $iStatus, $sType = null, $sLength = null)
01094     {
01095         //preparation
01096         $sName = strtolower( $sName );
01097 
01098         //adding field names element
01099         $this->_aFieldNames[$sName] = $iStatus;
01100 
01101         //already set?
01102         $sLongName = $this->_getFieldLongName($sName);
01103         if ( isset($this->$sLongName) ) {
01104             return;
01105         }
01106 
01107         //defining the field
01108         $oField = false;
01109 
01110         if ( isset( $sType ) ) {
01111             $oField = new oxField();
01112             $oField->fldtype = $sType;
01113             //T2008-01-29
01114             //can't clone as the fields are objects and are not fully cloned
01115             $this->_blIsSimplyClonable = false;
01116         }
01117 
01118         if ( isset( $sLength ) ) {
01119             if ( !$oField ) {
01120                 $oField = new oxField();
01121             }
01122             $oField->fldmax_length = $sLength;
01123             $this->_blIsSimplyClonable = false;
01124         }
01125 
01126         $this->$sLongName = $oField;
01127     }
01128 
01136     protected function _getFieldLongName( $sFieldName )
01137     {
01138         //trying to avoid strpos call as often as possible
01139         if ( $sFieldName[2] == $this->_sCoreTable[2] && strpos( $sFieldName, $this->_sCoreTable . "__" ) === 0 ) {
01140             return $sFieldName;
01141         }
01142 
01143         return $this->_sCoreTable . "__" . strtolower( $sFieldName );
01144     }
01145 
01155     protected function _setFieldData( $sFieldName, $sValue, $iDataType = oxField::T_TEXT)
01156     {
01157 
01158         $sLongFieldName = $this->_getFieldLongName( $sFieldName);
01159         //$sLongFieldName = $this->_sCoreTable . "__" . strtolower($sFieldName);
01160 
01161         //T2008-03-14
01162         //doing this because in lazy loaded lists on first load it is harmful to have initialised fields but not yet set
01163         //situation: only first article is loaded fully for "select oxid from oxarticles"
01164         /*
01165         if ($this->_blUseLazyLoading && !isset($this->$sLongFieldName))
01166             return;*/
01167 
01168         //in non lazy loading case we just add a field and do not care about it more
01169         if (!$this->_blUseLazyLoading && !isset($this->$sLongFieldName)) {
01170             $aFields = $this->_getAllFields(true);
01171             if ( isset( $aFields[strtolower($sFieldName)] ) ) {
01172                 $this->_addField($sFieldName, $this->_getFieldStatus($sFieldName));
01173             }
01174         }
01175         // if we have a double field we replace "," with "." in case somebody enters it in european format
01176         if (isset($this->$sLongFieldName) && isset($this->$sLongFieldName->fldtype) && $this->$sLongFieldName->fldtype == "double") {
01177             $sValue = str_replace( ",", ".", $sValue );
01178         }
01179 
01180         // isset is REQUIRED here not to use getter
01181         if (isset($this->$sLongFieldName) && is_object($this->$sLongFieldName)) {
01182             $this->$sLongFieldName->setValue($sValue, $iDataType);
01183         } else {
01184             $this->$sLongFieldName = new oxField($sValue, $iDataType);
01185         }
01186 
01187     }
01188 
01196     protected function _canFieldBeNull( $sFieldName )
01197     {
01198         $aMetaData = $this->_getAllFields();
01199         foreach ( $aMetaData as $oMetaInfo ) {
01200             if ( strcasecmp( $oMetaInfo->name, $sFieldName ) == 0 ) {
01201                 return !$oMetaInfo->not_null;
01202             }
01203         }
01204         return false;
01205     }
01206 
01207 
01215     protected function _getFieldDefaultValue( $sFieldName )
01216     {
01217         $aMetaData = $this->_getAllFields();
01218         foreach ( $aMetaData as $oMetaInfo ) {
01219             if ( strcasecmp( $oMetaInfo->name, $sFieldName ) == 0 ) {
01220                 return $oMetaInfo->default_value;
01221             }
01222         }
01223         return false;
01224     }
01225 
01226 
01235     protected function _getUpdateFieldValue( $sFieldName, $oField )
01236     {
01237         $mValue = null;
01238         if ( $oField instanceof oxField ) {
01239             $mValue = $oField->getRawValue();
01240         } elseif ( isset( $oField->value ) ) {
01241             $mValue = $oField->value;
01242         }
01243 
01244         $oDb = oxDb::getDb();
01245         //Check if this field value is null AND it can be null according if not returning default value
01246         if ( ( null === $mValue ) ) {
01247             if ( $this->_canFieldBeNull( $sFieldName ) ) {
01248                 return 'null';
01249             } elseif ( $mValue = $this->_getFieldDefaultValue( $sFieldName ) ) {
01250                 return $oDb->quote( $mValue );
01251             }
01252         }
01253 
01254         return $oDb->quote( $mValue );
01255     }
01256 
01265     protected function _getUpdateFields( $blUseSkipSaveFields = true )
01266     {
01267         $sSql = '';
01268         $blSep  = false;
01269 
01270         foreach (array_keys($this->_aFieldNames) as $sKey) {
01271             $sLongName = $this->_getFieldLongName($sKey);
01272             $oField = $this->$sLongName;
01273 
01274 
01275             if ( !$blUseSkipSaveFields || ($blUseSkipSaveFields && !in_array(strtolower($sKey), $this->_aSkipSaveFields)) ) {
01276                 $sSql .= (( $blSep) ? ',':'' ).$sKey." = ".$this->_getUpdateFieldValue($sKey, $oField);
01277                 $blSep = true;
01278             }
01279         }
01280 
01281         return $sSql;
01282     }
01283 
01293     protected function _update()
01294     {
01295         //do not allow derived item update
01296         if ( !$this->allowDerivedUpdate() ) {
01297             return false;
01298         }
01299 
01300 
01301         if ( !$this->getId() ) {
01302             $oEx = oxNew( 'oxObjectException' );
01303             $oEx->setMessage( 'EXCEPTION_OBJECT_OXIDNOTSET' );
01304             $oEx->setObject($this);
01305             throw $oEx;
01306         }
01307 
01308         $sIDKey = oxRegistry::getUtils()->getArrFldName( $this->_sCoreTable.".oxid");
01309         $this->$sIDKey = new oxField($this->getId(), oxField::T_RAW);
01310         $oDb = oxDb::getDb();
01311 
01312         $sUpdate= "update {$this->_sCoreTable} set ".$this->_getUpdateFields()
01313                  ." where {$this->_sCoreTable}.oxid = ".$oDb->quote( $this->getId() );
01314 
01315         //trigger event
01316         $this->beforeUpdate();
01317 
01318         $blRet = (bool) $oDb->execute( $sUpdate);
01319 
01320         return $blRet;
01321     }
01322 
01330     protected function _insert()
01331     {
01332 
01333         $oDb      = oxDb::getDb( oxDb::FETCH_MODE_ASSOC );
01334         $myConfig = $this->getConfig();
01335         $myUtils  = oxRegistry::getUtils();
01336 
01337         // let's get a new ID
01338         if ( !$this->getId()) {
01339             $this->setId();
01340         }
01341 
01342         $sIDKey = $myUtils->getArrFldName( $this->_sCoreTable.".oxid");
01343         $this->$sIDKey = new oxField($this->getId(), oxField::T_RAW);
01344         $sInsert= "Insert into {$this->_sCoreTable} set ";
01345 
01346         //setting oxshopid
01347         $sShopField = $myUtils->getArrFldName($this->_sCoreTable.".oxshopid");
01348 
01349         if (isset($this->$sShopField) && !$this->$sShopField->value) {
01350             $this->$sShopField = new oxField($myConfig->getShopId(), oxField::T_RAW);
01351         }
01352 
01353 
01354         $sInsert .= $this->_getUpdateFields( $this->getUseSkipSaveFields() );
01355 
01356         $blRet = (bool) $oDb->execute( $sInsert );
01357 
01358         return $blRet;
01359     }
01360 
01367     protected function _isDisabledFieldCache()
01368     {
01369         $sClass = get_class($this);
01370         if (isset(self::$_blDisableFieldCaching[$sClass]) && self::$_blDisableFieldCaching[$sClass]) {
01371             return true;
01372         }
01373 
01374         return false;
01375     }
01376 
01382     public function isOx()
01383     {
01384         $sOxId = $this->getId();
01385         if ( $sOxId[0] == 'o' && $sOxId[1] == 'x' ) {
01386             return true;
01387         }
01388         return false;
01389     }
01390 
01396     public function isReadOnly()
01397     {
01398         return $this->_blReadOnly;
01399     }
01400 
01408     public function setReadOnly( $blReadOnly )
01409     {
01410         $this->_blReadOnly = $blReadOnly;
01411     }
01412 
01418     public function getFieldNames()
01419     {
01420         return array_keys( $this->_aFieldNames );
01421     }
01422 
01430     public function addFieldName( $sName )
01431     {
01432         //preparation
01433         $sName = strtolower( $sName );
01434         $this->_aFieldNames[$sName] = 0;
01435     }
01436 
01437 
01443     public function getLanguage()
01444     {
01445         return -1;
01446     }
01447 
01448 }