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 
00044     protected $_aErrors = array();
00045 
00050     protected $_sClassName = 'oxbase';
00051 
00057     protected $_sCoreTable = null;
00058 
00063     protected $_sViewTable  = null;
00064 
00065 
00071     protected $_aFieldNames = array('oxid' => 0);
00072 
00077     protected $_blIsNewCache = false;
00078 
00084     protected $_sCacheKey = null;
00085 
00091     protected $_blUseLazyLoading = false;
00092 
00098     protected $_aSkipSaveFields = array();
00099 
00104     protected $_sExistKey = "oxid";
00105 
00112     protected $_blIsDerived = null;
00113 
00123     protected static $_blDisableFieldCaching = array();
00124 
00130     protected $_blIsSeoObject = false;
00131 
00137     protected $_blReadOnly = false;
00138 
00144     protected $_blIsInList = false;
00145 
00151     protected $_isLoaded = false;
00152 
00158     protected $_aInnerLazyCache = null;
00159 
00165     protected $_blEmployMultilanguage = false;
00166 
00170     public function __construct()
00171     {
00172         // set active shop
00173         $myConfig = $this->getConfig();
00174         $this->_sCacheKey = $this->getViewName();
00175         if ( $this->_blUseLazyLoading ) {
00176             $this->_sCacheKey .= $myConfig->getActiveView()->getClassName();
00177         } else {
00178             $this->_sCacheKey .= "allviews";
00179         }
00180 
00181         //do not cache for admin?
00182         if ( $this->isAdmin() ) {
00183             $this->_sCacheKey = null;
00184         }
00185 
00186         $this->setShopId( $myConfig->getShopId() );
00187     }
00188 
00197     public function __set( $sName, $sValue )
00198     {
00199         $this->$sName = $sValue;
00200         if ( $this->_blUseLazyLoading && strpos( $sName, $this->_sCoreTable . "__" ) === 0 ) {
00201             $sFieldName = str_replace( $this->_sCoreTable . "__", '', $sName );
00202             if ( $sFieldName != 'oxnid' && ( !isset( $this->_aFieldNames[$sFieldName] ) || !$this->_aFieldNames[$sFieldName] ) ) {
00203                 $aAllFields = $this->_getAllFields(true);
00204                 if ( isset( $aAllFields[strtolower($sFieldName)] ) ) {
00205                     $iFieldStatus = $this->_getFieldStatus( $sFieldName );
00206                     $this->_addField( $sFieldName, $iFieldStatus );
00207                 }
00208             }
00209         }
00210     }
00211 
00219     public function __get( $sName )
00220     {
00221         switch ( $sName ) {
00222             case 'blIsDerived':
00223                 return $this->isDerived();
00224                 break;
00225             case 'sOXID':
00226                 return $this->getId();
00227                 break;
00228             case 'blReadOnly':
00229                 return $this->isReadOnly();
00230                 break;
00231         }
00232 
00233         // implementing lazy loading fields
00234         // This part of the code is slow and normally is called before field cache is built.
00235         // Make sure it is not called after first page is loaded and cache data is fully built.
00236         if ( $this->_blUseLazyLoading && stripos( $sName, $this->_sCoreTable . "__" ) === 0 ) {
00237 
00238             if ( $this->getId() ) {
00239 
00240                 //lazy load it
00241                 $sFieldName      = str_replace( $this->_sCoreTable . "__", '', $sName );
00242                 $sCacheFieldName = strtoupper( $sFieldName );
00243 
00244                 $iFieldStatus = $this->_getFieldStatus( $sFieldName );
00245                 $sViewName    = $this->getViewName();
00246                 $sId = $this->getId();
00247 
00248                 try {
00249                     if ( $this->_aInnerLazyCache === null ) {
00250 
00251                         $oDb = oxDb::getDb( true );
00252                         $sQ = "SELECT * FROM " . $sViewName . " WHERE `oxid` = " . $oDb->quote( $sId );
00253                         $rs = $oDb->execute( $sQ );
00254                         if (  $rs && $rs->RecordCount() ) {
00255                             $this->_aInnerLazyCache = array_change_key_case( $rs->fields, CASE_UPPER );
00256                             if ( array_key_exists( $sCacheFieldName, $rs->fields ) ) {
00257                                 $sFieldValue = $rs->fields[$sCacheFieldName];
00258                             } else {
00259                                 return null;
00260                             }
00261                         } else {
00262                             return null;
00263                         }
00264                     } elseif ( array_key_exists( $sCacheFieldName, $this->_aInnerLazyCache ) ) {
00265                         $sFieldValue = $this->_aInnerLazyCache[$sCacheFieldName];
00266                     } else {
00267                         return null;
00268                     }
00269 
00270                     $this->_addField( $sFieldName, $iFieldStatus );
00271                     $this->_setFieldData( $sFieldName, $sFieldValue );
00272 
00273                     //save names to cache for next loading
00274                     if ($this->_sCacheKey) {
00275                         $myUtils = oxUtils::getInstance();
00276                         $sCacheKey = 'fieldnames_' . $this->_sCoreTable . "_" . $this->_sCacheKey;
00277                         $aFieldNames = $myUtils->fromFileCache( $sCacheKey );
00278                         $aFieldNames[$sFieldName] = $iFieldStatus;
00279                         $myUtils->toFileCache( $sCacheKey, $aFieldNames );
00280                     }
00281                 } catch ( Exception $e ) {
00282                     return null;
00283                 }
00284 
00285                 //do not use field cache for this page
00286                 //as if we use it for lists then objects are loaded empty instead of lazy loading.
00287                 self::$_blDisableFieldCaching[get_class( $this )] = true;
00288             }
00289 
00290             oxUtilsObject::getInstance()->resetInstanceCache(get_class($this));
00291         }
00292 
00293         //returns oxStdClass implementing __toString() method due to uknown scenario where this var should be used.
00294         if (!isset( $this->$sName ) ) {
00295             $this->$sName = null;
00296         }
00297 
00298         return $this->$sName;
00299     }
00300 
00308     public function __isset($mVar)
00309     {
00310         return isset($this->$mVar);
00311     }
00312 
00318     public function __clone()
00319     {
00320         if (!$this->_blIsSimplyClonable) {
00321             foreach ( $this->_aFieldNames as $sField => $sVal ) {
00322                 $sLongName = $this->_getFieldLongName( $sField );
00323                 if ( is_object($this->$sLongName)) {
00324                     $this->$sLongName = clone $this->$sLongName;
00325                 }
00326             }
00327         }
00328     }
00329 
00337     public function oxClone($oObject)
00338     {
00339         $aClasVars = get_object_vars( $oObject);
00340         while (list($name, $value) = each($aClasVars)) {
00341             if ( is_object( $oObject->$name ) ) {
00342                 $this->$name = clone $oObject->$name;
00343             } else {
00344                 $this->$name = $oObject->$name;
00345             }
00346         }
00347     }
00348 
00357     public function init( $sTableName = null, $blForceAllFields = false)
00358     {
00359 
00360         if ( !$sTableName ) {
00361             $sTableName = $this->_sCoreTable;
00362         } else {
00363             $this->_sCoreTable = $sTableName;
00364         }
00365 
00366         // reset view table
00367         $this->_sViewTable = false;
00368 
00369         if ( count( $this->_aFieldNames ) <= 1 ) {
00370             $this->_initDataStructure( $blForceAllFields );
00371         }
00372     }
00373 
00381     public function assign( $dbRecord )
00382     {
00383         if ( !is_array( $dbRecord ) ) {
00384             return;
00385         }
00386 
00387 
00388         reset($dbRecord );
00389         while ( list( $sName, $sValue ) = each( $dbRecord ) ) {
00390 
00391             // patch for IIS
00392             //TODO: test it on IIS do we still need it
00393             //if( is_array($value) && count( $value) == 1)
00394             //    $value = current( $value);
00395 
00396             $this->_setFieldData( $sName, $sValue );
00397         }
00398 
00399         $sOxidField = $this->_getFieldLongName( 'oxid' );
00400         $this->_sOXID = $this->$sOxidField->value;
00401 
00402     }
00403 
00409     public function getClassName()
00410     {
00411         return $this->_sClassName;
00412     }
00413 
00419     public function getCoreTableName()
00420     {
00421         return $this->_sCoreTable;
00422     }
00423 
00429     public function getId()
00430     {
00431         return $this->_sOXID;
00432     }
00433 
00441     public function setId($sOXID = null)
00442     {
00443         if ( $sOXID ) {
00444             $this->_sOXID = $sOXID;
00445         } else {
00446             $this->_sOXID = oxUtilsObject::getInstance()->generateUID();
00447         }
00448 
00449         $sIdVarName = $this->_sCoreTable . "__oxid";
00450         $this->$sIdVarName = new oxField($this->_sOXID, oxField::T_RAW);
00451 
00452         return $this->_sOXID;
00453     }
00454 
00462     public function setShopId($iShopId)
00463     {
00464         $this->_iShopId = $iShopId;
00465     }
00466 
00472     public function getShopId()
00473     {
00474         return $this->_iShopId;
00475     }
00476 
00484     public function getViewName($blForceCoreTableUsage = null)
00485     {
00486         if (!$this->_sViewTable || ($blForceCoreTableUsage !== null)) {
00487             if ( $blForceCoreTableUsage === true ) {
00488                 return $this->_sCoreTable;
00489             }
00490 
00491             if ( ( $blForceCoreTableUsage !== null ) ? $blForceCoreTableUsage : $this->_blForceCoreTableUsage ) {
00492                 $iShopId = -1;
00493             } else {
00494                 $iShopId = oxConfig::getInstance()->getShopId();
00495             }
00496             $sViewName = getViewName( $this->_sCoreTable, $this->_blEmployMultilanguage == false ? -1 : $this->getLanguage(), $iShopId );
00497             if ( $blForceCoreTableUsage !== null ) {
00498                 return $sViewName;
00499             }
00500             $this->_sViewTable = $sViewName;
00501         }
00502         return $this->_sViewTable;
00503     }
00504 
00513     public function modifyCacheKey( $sCacheKey, $blOverride = false )
00514     {
00515         if ( $blOverride ) {
00516             $this->_sCacheKey = $sCacheKey;
00517         } else {
00518             $this->_sCacheKey .= $sCacheKey;
00519         }
00520     }
00521 
00527     public function disableLazyLoading()
00528     {
00529         $this->_blUseLazyLoading = false;
00530         $this->_initDataStructure(true);
00531     }
00532 
00533 
00539     public function isDerived()
00540     {
00541 
00542         return $this->_blIsDerived;
00543     }
00544 
00552     public function setIsDerived($blVal)
00553     {
00554         $this->_blIsDerived = $blVal;
00555     }
00556 
00563     public function isMultilang()
00564     {
00565         return false;
00566     }
00567 
00577     public function load( $sOXID)
00578     {
00579         /*
00580         if( !isset($oxID)){
00581             $oEx = oxNew('oxObjectException','core');
00582             $oEx->setMessage('EXCEPTION_OBJECT_OXIDNOTSET');
00583             $oEx->setObject($this);
00584             throw $oEx;
00585         }*/
00586 
00587         //getting at least one field before lazy loading the object
00588         $this->_addField('oxid', 0);
00589         $sSelect = $this->buildSelectString( array( $this->getViewName().".oxid" => $sOXID));
00590 
00591         return $this->_isLoaded = $this->assignRecord( $sSelect );
00592     }
00593 
00599     public function isLoaded()
00600     {
00601         return $this->_isLoaded;
00602     }
00603 
00611     public function buildSelectString( $aWhere = null)
00612     {
00613         $oDB = oxDb::getDb(true);
00614         $myUtils = oxUtils::getInstance();
00615 
00616         $sGet = $this->getSelectFields();
00617         $sSelect = "select $sGet from " . $this->getViewName() . " where 1 ";
00618 
00619         if ( $aWhere) {
00620             reset($aWhere);
00621             while (list($name, $value) = each($aWhere)) {
00622                 $sSelect .=  " and " . $name.' = '.$oDB->quote($value);
00623             }
00624         }
00625 
00626         // add active shop
00627 
00628         return $sSelect;
00629     }
00630 
00638     public function assignRecord( $sSelect)
00639     {
00640         $blRet = false;
00641 
00642         $oDB = oxDb::getDb(true);
00643 
00644         $rs = $oDB->execute( $sSelect);
00645         if ($rs != false && $rs->recordCount() > 0) {
00646             $blRet = true;
00647             $this->assign( $rs->fields);
00648         }
00649 
00650         return $blRet;
00651     }
00652 
00660     public function getFieldData( $sFieldName )
00661     {
00662         $sLongFieldName = $this->_getFieldLongName( $sFieldName );
00663             return $this->$sLongFieldName->value;
00664     }
00665 
00673     public function getSelectFields( $blForceCoreTableUsage = null )
00674     {
00675         $aSelectFields = array();
00676 
00677         $sViewName = $this->getViewName( $blForceCoreTableUsage );
00678 
00679         foreach ( $this->_aFieldNames as $sKey => $sField ) {
00680             $aSelectFields[] = $sViewName . '.' . $sKey;
00681         }
00682 
00683         $sSelectFields = join( ", ", $aSelectFields );
00684         return $sSelectFields;
00685     }
00686 
00694     public function delete( $sOXID = null)
00695     {
00696         if ( !$sOXID ) {
00697             $sOXID = $this->getId();
00698 
00699             //do not allow derived deletion
00700             if ( !$this->allowDerivedDelete() ) {
00701                 return false;
00702             }
00703         }
00704 
00705         if ( !$sOXID ) {
00706             return false;
00707         }
00708 
00709 
00710         $oDB = oxDb::getDb(true);
00711         $sDelete = "delete from $this->_sCoreTable where oxid = ".$oDB->quote( $sOXID );
00712         $rs = $oDB->execute( $sDelete );
00713         if ( $blDelete = ( bool ) $oDB->affected_Rows() ) {
00714             $this->onChange(ACTION_DELETE, $sOXID);
00715         }
00716 
00717         return $blDelete;
00718     }
00719 
00720 
00726     public function save()
00727     {
00728         if ( !is_array( $this->_aFieldNames ) ) {
00729             return false;
00730         }
00731 
00732         $blRet = false;
00733 
00734         // #739A - should be executed here because of date/time formatting feature
00735         if ( $this->isAdmin() && !$this->getConfig()->getConfigParam( 'blSkipFormatConversion' ) ) {
00736             foreach ($this->_aFieldNames as $sName => $sVal) {
00737                 $sLongName = $this->_getFieldLongName($sName);
00738                 if ( isset($this->$sLongName->fldtype) && $this->$sLongName->fldtype == "datetime" ) {
00739                     oxDb::getInstance()->convertDBDateTime( $this->$sLongName, true );
00740                 } elseif ( isset($this->$sLongName->fldtype) && $this->$sLongName->fldtype == "timestamp" ) {
00741                     oxDb::getInstance()->convertDBTimestamp( $this->$sLongName, true);
00742                 } elseif ( isset($this->$sLongName->fldtype) && $this->$sLongName->fldtype == "date" ) {
00743                     oxDb::getInstance()->convertDBDate( $this->$sLongName, true);
00744                 }
00745             }
00746         }
00747         if ( $this->exists() ) {
00748             //do not allow derived update
00749             if ( !$this->allowDerivedUpdate() ) {
00750                 return false;
00751             }
00752 
00753             $blRet = $this->_update();
00754             $sAction = ACTION_UPDATE;
00755         } else {
00756             $blRet = $this->_insert();
00757             $sAction = ACTION_INSERT;
00758         }
00759 
00760         $this->onChange($sAction);
00761 
00762         if ( $blRet ) {
00763             return $this->getId();
00764         } else {
00765             return false;
00766         }
00767     }
00768 
00774     public function allowDerivedUpdate()
00775     {
00776         return !$this->isDerived();
00777     }
00778 
00784     public function allowDerivedDelete()
00785     {
00786         return !$this->isDerived();
00787     }
00788 
00796     public function exists( $sOXID = null)
00797     {
00798         if ( !$sOXID ) {
00799             $sOXID = $this->getId();
00800         }
00801         if ( !$sOXID ) {
00802             return false;
00803         }
00804 
00805         $sViewName = $this->getCoreTableName();
00806         $oDB = oxDb::getDb( true );
00807         $sSelect= "select {$this->_sExistKey} from {$sViewName} where {$this->_sExistKey} = ".$oDB->quote( $sOXID );
00808 
00809         return ( bool ) $oDB->getOne( $sSelect );
00810     }
00811 
00819     public function getSqlActiveSnippet( $blForceCoreTable = null )
00820     {
00821         $sQ = '';
00822         $sTable = $this->getViewName($blForceCoreTable);
00823 
00824         // has 'active' field ?
00825         if ( isset( $this->_aFieldNames['oxactive'] ) ) {
00826             $sQ = " $sTable.oxactive = 1 ";
00827         }
00828 
00829         // has 'activefrom'/'activeto' fields ?
00830         if ( isset( $this->_aFieldNames['oxactivefrom'] ) && isset( $this->_aFieldNames['oxactiveto'] ) ) {
00831 
00832             $sDate = date( 'Y-m-d H:i:s', oxUtilsDate::getInstance()->getTime() );
00833 
00834             $sQ = $sQ?" $sQ or ":'';
00835             $sQ = " ( $sQ ( $sTable.oxactivefrom < '$sDate' and $sTable.oxactiveto > '$sDate' ) ) ";
00836         }
00837 
00838         return $sQ;
00839     }
00840 
00849     public function validate()
00850     {
00851         $this->_aErrors = array();
00852         foreach ($this->_aFieldNames as $fName => $iVal) {
00853 
00854             $fName = $this->_getFieldLongName($fName);
00855 
00856             if ( method_exists ( $this, "validate_$fName")) {
00857                 $validatorMethod = "validate_$fName";
00858                 if ( $error = $this->$validatorMethod()) {
00859                     $this->_aErrors[$fName] = $error;
00860                 }
00861             }
00862         }
00863         return !$this->hasErrors();
00864     }
00865 
00874     public function beforeUpdate( $sOXID = null )
00875     {
00876     }
00877 
00888     public function onChange( $iAction = null, $sOXID = null)
00889     {
00890     }
00891 
00892 
00900     public function hasErrors()
00901     {
00902         return count($this->_aErrors) > 0;
00903     }
00904 
00912     public function getErrors()
00913     {
00914         return $this->_aErrors;
00915     }
00916 
00926     public function getError( $sField)
00927     {
00928         if (isset($this->_aErrors[$sField])) {
00929             return $this->_aErrors[$sField];
00930         }
00931 
00932         //T2007-10-19
00933         //return array();
00934         return null;
00935     }
00936 
00946     public function getHtmlError( $sField)
00947     {
00948         if ( $error = $this->getError($sField) ) {
00949             return $error;
00950         }
00951     }
00952 
00958     public function setInList()
00959     {
00960         $this->_blIsInList = true;
00961     }
00962 
00968     protected function _isInList()
00969     {
00970         return $this->_blIsInList;
00971     }
00972 
00981     protected function _getObjectViewName( $sTable, $sShopID = null)
00982     {
00983         if ( $this->_blForceCoreTableUsage ) {
00984             $sShopID = -1;
00985         }
00986         return getViewName( $sTable, -1, $sShopID);
00987     }
00988 
00989 
01000     protected function _getTableFields($sTable, $blReturnSimple = false)
01001     {
01002         $myUtils = oxUtils::getInstance();
01003 
01004         $sCacheKey   = $sTable . "_allfields_" . $blReturnSimple;
01005         $aMetaFields = $myUtils->fromFileCache( $sCacheKey );
01006 
01007         if ( $aMetaFields ) {
01008             return $aMetaFields;
01009         }
01010 
01011         $aMetaFields = oxDb::getInstance()->getTableDescription( $sTable );
01012 
01013         if ( !$blReturnSimple ) {
01014             $myUtils->toFileCache( $sCacheKey, $aMetaFields );
01015             return $aMetaFields;
01016         }
01017 
01018         //returning simple array
01019         $aRet = array();
01020         if (is_array($aMetaFields)) {
01021             foreach ( $aMetaFields as $oVal ) {
01022                 $aRet[strtolower( $oVal->name )] = 0;
01023             }
01024         }
01025 
01026         $myUtils->toFileCache( $sCacheKey, $aRet);
01027 
01028         return $aRet;
01029     }
01030 
01042     protected function _getAllFields($blReturnSimple = false)
01043     {
01044         if (!$this->_sCoreTable) {
01045             return array();
01046         }
01047         return $this->_getTableFields($this->_sCoreTable, $blReturnSimple);
01048     }
01049 
01058     protected function _initDataStructure($blForceFullStructure = false)
01059     {
01060         $myUtils = oxUtils::getInstance();
01061 
01062         //get field names from cache
01063         $aFieldNames = null;
01064         $sFullCacheKey = 'fieldnames_' .$this->_sCoreTable . "_" . $this->_sCacheKey;
01065         if ($this->_sCacheKey && !$this->_isDisabledFieldCache()) {
01066             $aFieldNames = $myUtils->fromFileCache($sFullCacheKey);
01067         }
01068 
01069         if (!$aFieldNames) {
01070             $aFieldNames = $this->_getNonCachedFieldNames($blForceFullStructure);
01071             if ($this->_sCacheKey && !$this->_isDisabledFieldCache()) {
01072                 $myUtils->toFileCache($sFullCacheKey, $aFieldNames);
01073             }
01074         }
01075 
01076         if ( $aFieldNames !== false ) {
01077             foreach ( $aFieldNames as $sField => $sStatus ) {
01078                 $this->_addField($sField, $sStatus);
01079             }
01080         }
01081     }
01082 
01094     protected function _getNonCachedFieldNames($blForceFullStructure = false)
01095     {
01096         //T2008-02-22
01097         //so if this method is executed on cached version we see it when profiling
01098         startProfile("!__CACHABLE__!");
01099 
01100         //case 1. (admin)
01101         if ($this->isAdmin()) {
01102             $aMetaFields = $this->_getAllFields();
01103             foreach ( $aMetaFields as $oField ) {
01104                 if ( $oField->max_length == -1 ) {
01105                     $oField->max_length = 10;      // double or float
01106                 }
01107 
01108                 if ( $oField->type == "datetime" ) {
01109                     $oField->max_length = 20;
01110                 }
01111 
01112                 $this->_addField( $oField->name, $this->_getFieldStatus($oField->name), $oField->type, $oField->max_length );
01113             }
01114             stopProfile("!__CACHABLE__!");
01115             return false;
01116         }
01117 
01118         //case 2. (just get all fields)
01119         if ( $blForceFullStructure || !$this->_blUseLazyLoading ) {
01120             $aMetaFields = $this->_getAllFields(true);
01121             /*
01122             foreach ( $aMetaFields as $sFieldName => $sVal) {
01123                 $this->_addField( $sFieldName, $this->_getFieldStatus($sFieldName));
01124             }*/
01125             stopProfile("!__CACHABLE__!");
01126             return $aMetaFields;
01127         }
01128 
01129         //case 3. (get only oxid field, so we can fetch the rest of the fields over lazy loading mechanism)
01130         stopProfile("!__CACHABLE__!");
01131         return array("oxid" => 0);
01132     }
01133 
01142     protected function _getFieldStatus( $sFieldName )
01143     {
01144         return 0;
01145     }
01146 
01157     protected function _addField($sName, $iStatus, $sType = null, $sLength = null)
01158     {
01159         //preparation
01160         $sName = strtolower( $sName );
01161 
01162         //adding field names element
01163         $this->_aFieldNames[$sName] = $iStatus;
01164 
01165         //allready set?
01166         $sLongName = $this->_getFieldLongName($sName);
01167         if ( isset($this->$sLongName) ) {
01168             return;
01169         }
01170 
01171         //defining the field
01172         $oField = false;
01173 
01174         if ( isset( $sType ) ) {
01175             $oField = new oxField();
01176             $oField->fldtype = $sType;
01177             //T2008-01-29
01178             //can't clone as the fields are objects and are not fully cloned
01179             $this->_blIsSimplyClonable = false;
01180         }
01181 
01182         if ( isset( $sLength ) ) {
01183             if ( !$oField ) {
01184                 $oField = new oxField();
01185             }
01186             $oField->fldmax_length = $sLength;
01187             $this->_blIsSimplyClonable = false;
01188         }
01189 
01190         $this->$sLongName = $oField;
01191     }
01192 
01200     protected function _getFieldLongName( $sFieldName )
01201     {
01202         //trying to avoid strpos call as often as possible
01203         if ( $sFieldName[2] == $this->_sCoreTable[2] && strpos( $sFieldName, $this->_sCoreTable . "__" ) === 0 ) {
01204             return $sFieldName;
01205         }
01206 
01207         return $this->_sCoreTable . "__" . strtolower( $sFieldName );
01208     }
01209 
01219     protected function _setFieldData( $sFieldName, $sValue, $iDataType = oxField::T_TEXT)
01220     {
01221 
01222         $sLongFieldName = $this->_getFieldLongName( $sFieldName);
01223         //$sLongFieldName = $this->_sCoreTable . "__" . strtolower($sFieldName);
01224 
01225         //T2008-03-14
01226         //doing this because in lazy loaded lists on first load it is harmful to have initilised fields but not yet set
01227         //situation: only first article is loaded fully for "select oxid from oxarticles"
01228         /*
01229         if ($this->_blUseLazyLoading && !isset($this->$sLongFieldName))
01230             return;*/
01231 
01232         //in non lazy loading case we just add a field and do not care about it more
01233         if (!$this->_blUseLazyLoading && !isset($this->$sLongFieldName)) {
01234             $aFields = $this->_getAllFields(true);
01235             if ( isset( $aFields[strtolower($sFieldName)] ) ) {
01236                 $this->_addField($sFieldName, $this->_getFieldStatus($sFieldName));
01237             }
01238         }
01239         // if we have a double field we replace "," with "." in case somebody enters it in european format
01240         if (isset($this->$sLongFieldName) && isset($this->$sLongFieldName->fldtype) && $this->$sLongFieldName->fldtype == "double") {
01241             $sValue = str_replace( ",", ".", $sValue );
01242         }
01243 
01244         // isset is REQUIRED here not to use getter
01245         if (isset($this->$sLongFieldName) && is_object($this->$sLongFieldName)) {
01246             $this->$sLongFieldName->setValue($sValue, $iDataType);
01247         } else {
01248             $this->$sLongFieldName = new oxField($sValue, $iDataType);
01249         }
01250 
01251     }
01252 
01260     protected function _canFieldBeNull( $sFieldName )
01261     {
01262         $aMetaData = $this->_getAllFields();
01263         foreach ( $aMetaData as $oMetaInfo ) {
01264             if ( strcasecmp( $oMetaInfo->name, $sFieldName ) == 0 ) {
01265                 return !$oMetaInfo->not_null;
01266             }
01267         }
01268         return false;
01269     }
01270 
01279     protected function _getUpdateFieldValue( $sFieldName, $oField )
01280     {
01281         $mValue = null;
01282         if ( $oField instanceof oxField ) {
01283             $mValue = $oField->getRawValue();
01284         } elseif ( isset( $oField->value ) ) {
01285             $mValue = $oField->value;
01286         }
01287         // Sarunas. check if this field value is null AND it can be null according to table description
01288         if ( ( null === $mValue ) && $this->_canFieldBeNull( $sFieldName ) ) {
01289             return 'null';
01290         }
01291         return oxDb::getDb()->quote( $mValue );
01292     }
01293 
01302     protected function _getUpdateFields( $blUseSkipSaveFields = true )
01303     {
01304         $sSql = '';
01305         $blSep  = false;
01306 
01307         foreach (array_keys($this->_aFieldNames) as $sKey) {
01308             $sLongName = $this->_getFieldLongName($sKey);
01309             $oField = $this->$sLongName;
01310 
01311 
01312             if ( !$blUseSkipSaveFields || ($blUseSkipSaveFields && !in_array(strtolower($sKey), $this->_aSkipSaveFields)) ) {
01313                 $sSql .= (( $blSep) ? ',':'' ).$sKey." = ".$this->_getUpdateFieldValue($sKey, $oField);
01314                 $blSep = true;
01315             }
01316         }
01317 
01318         return $sSql;
01319     }
01320 
01330     protected function _update()
01331     {
01332         //do not allow derived item update
01333         if ( !$this->allowDerivedUpdate() ) {
01334             return false;
01335         }
01336 
01337 
01338         if ( !$this->getId() ) {
01339             $oEx = oxNew( 'oxObjectException' );
01340             $oEx->setMessage( 'EXCEPTION_OBJECT_OXIDNOTSET' );
01341             $oEx->setObject($this);
01342             throw $oEx;
01343         }
01344 
01345         $sIDKey = oxUtils::getInstance()->getArrFldName( $this->_sCoreTable.".oxid");
01346         $this->$sIDKey = new oxField($this->getId(), oxField::T_RAW);
01347         $oDb = oxDB::getDb();
01348 
01349         $sUpdate= "update {$this->_sCoreTable} set ".$this->_getUpdateFields()
01350                  ." where {$this->_sCoreTable}.oxid = ".$oDb->quote( $this->getId() );
01351 
01352         //trigger event
01353         $this->beforeUpdate();
01354 
01355         $blRet = (bool) $oDb->execute( $sUpdate);
01356         $this->_rebuildCache();
01357 
01358         return $blRet;
01359     }
01360 
01368     protected function _insert()
01369     {
01370 
01371         $oDB      = oxDb::getDb(true);
01372         $myConfig = $this->getConfig();
01373         $myUtils  = oxUtils::getInstance();
01374 
01375         // let's get a new ID
01376         if ( !$this->getId()) {
01377             $this->setId();
01378         }
01379 
01380         $sIDKey = $myUtils->getArrFldName( $this->_sCoreTable.".oxid");
01381         $this->$sIDKey = new oxField($this->getId(), oxField::T_RAW);
01382         $sInsert= "Insert into {$this->_sCoreTable} set ";
01383 
01384         //setting oxshopid
01385         $sShopField = $myUtils->getArrFldName($this->_sCoreTable.".oxshopid");
01386         if (isset($this->$sShopField) && !$this->$sShopField->value)
01387             $this->$sShopField = new oxField($myConfig->getShopId(), oxField::T_RAW);
01388 
01389         $sInsert .= $this->_getUpdateFields( false );
01390         $blRet = (bool) $oDB->execute( $sInsert);
01391 
01392         $this->_rebuildCache();
01393 
01394         return $blRet;
01395 
01396     }
01397 
01403     protected function _rebuildCache()
01404     {
01405         if ( !$this->_blIsNewCache) {
01406             oxUtils::getInstance()->rebuildCache();
01407             $this->_blIsNewCache = true;
01408         }
01409     }
01410 
01420     protected function _setRecordNumber( $sMaxField, $aWhere = null, $iMaxTryCnt = 5 )
01421     {
01422         // filtering
01423         $sWhere = "";
01424         if ( is_array( $aWhere ) && count( $aWhere ) > 0) {
01425             $sWhere = implode(" and ", $aWhere).' and ';
01426         }
01427         $oDb = oxDb::getDb(true);
01428 
01429         // SQL to set record number
01430         $sUpdate = "update {$this->getViewName()} as t1, (select (max($sMaxField)+1) as t2max from {$this->getViewName()} where $sWhere 1) as t2 set t1.$sMaxField=t2.t2max where t1.oxid = ".$oDb->quote( $this->getId() );
01431 
01432         // SQL to check record number dublicates
01433         //this should not happen normally but we prefer to take extra care in this case due to parallel script execution etc.
01434         $sMaxSelect = "select $sMaxField from ".$this->getViewName()." where oxid=".$oDb->quote( $this->getId() );
01435         $sCheck = "select count(oxid) from ".$this->getViewName()." where $sMaxField = ($sMaxSelect) and $sWhere 1 ";
01436 
01437         do {
01438             if ( $oDb->execute( $sUpdate ) === false ) {
01439                 return false;
01440             }
01441 
01442             $iChkCnt = $oDb->getOne( $sCheck );
01443         } while ( ( $iChkCnt > 1 ) && $iMaxTryCnt-- );
01444 
01445         $sFieldName = $this->getViewName().'__'.$sMaxField;
01446         $this->$sFieldName = new oxField( $oDb->getOne( $sMaxSelect ), oxField::T_RAW);//int value
01447 
01448         return ( $iChkCnt == 1 );
01449     }
01450 
01457     protected function _isDisabledFieldCache()
01458     {
01459         $sClass = get_class($this);
01460         if (isset(self::$_blDisableFieldCaching[$sClass]) && self::$_blDisableFieldCaching[$sClass]) {
01461             return true;
01462         }
01463 
01464         return false;
01465     }
01466 
01472     public function isOx()
01473     {
01474         $sOxId = $this->getId();
01475         if ( $sOxId[0] == 'o' && $sOxId[1] == 'x' ) {
01476             return true;
01477         }
01478         return false;
01479     }
01480 
01486     public function isReadOnly()
01487     {
01488         return $this->_blReadOnly;
01489     }
01490 
01498     public function setReadOnly( $blReadOnly )
01499     {
01500         $this->_blReadOnly = $blReadOnly;
01501     }
01502 
01508     public function getFieldNames()
01509     {
01510         return array_keys( $this->_aFieldNames );
01511     }
01512 
01518     public function getLanguage()
01519     {
01520         return -1;
01521     }
01522 }