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 
00156     public function __construct()
00157     {
00158         // set active shop
00159         $myConfig = $this->getConfig();
00160         $this->_sCacheKey = $this->getViewName();
00161         if ( $this->_blUseLazyLoading ) {
00162             $this->_sCacheKey .= $myConfig->getActiveView()->getClassName();
00163         } else {
00164             $this->_sCacheKey .= "allviews";
00165         }
00166 
00167         //do not cache for admin?
00168         if ( $this->isAdmin() ) {
00169             $this->_sCacheKey = null;
00170         }
00171 
00172         $this->setShopId( $myConfig->getShopId() );
00173     }
00174 
00183     public function __set( $sName, $sValue )
00184     {
00185         $this->$sName = $sValue;
00186         if ( $this->_blUseLazyLoading && strpos( $sName, $this->_sCoreTable . "__" ) === 0 ) {
00187             $sFieldName = str_replace( $this->_sCoreTable . "__", '', $sName );
00188             if ($sFieldName != 'oxnid' && !$this->_aFieldNames[$sFieldName]) {
00189                 $aAllFields = $this->_getAllFields(true);
00190                 if (isset($aAllFields[strtolower($sFieldName)])) {
00191                     $iFieldStatus = $this->_getFieldStatus($sFieldName);
00192                     $this->_addField($sFieldName, $iFieldStatus);
00193                 }
00194             }
00195         }
00196     }
00197 
00205     public function __get( $sName )
00206     {
00207         switch ( $sName ) {
00208             case 'blIsDerived':
00209                 return $this->isDerived();
00210                 break;
00211             case 'sOXID':
00212                 return $this->getId();
00213                 break;
00214             case 'blReadOnly':
00215                 return $this->isReadOnly();
00216                 break;
00217         }
00218 
00219         // implementing lazy loading fields
00220         // This part of the code is slow and normally is called before field cache is built.
00221         // Make sure it is not called after first page is loaded and cache data is fully built.
00222         if ( $this->_blUseLazyLoading && stripos( $sName, $this->_sCoreTable . "__" ) === 0 ) {
00223 
00224             if ( $this->getId() ) {
00225 
00226                 //lazy load it
00227                 $sFieldName = str_replace($this->_sCoreTable . "__", '', $sName);
00228                 $iFieldStatus = $this->_getFieldStatus($sFieldName);
00229 
00230                 $oDb = oxDb::getDb();
00231                 $sQ = "select $sFieldName from " . $this->getViewName() . " where oxid = " . $oDb->quote($this->getId());
00232 
00233                 try {
00234                     $rs = $oDb->execute( $sQ );
00235                     if ( $rs === false ) {
00236                         return null;
00237                     }
00238 
00239                     $this->_addField( $sFieldName, $iFieldStatus );
00240                     $this->_setFieldData( $sFieldName, $rs->fields[0] );
00241 
00242                     //save names to cache for next loading
00243                     if ($this->_sCacheKey) {
00244                         $myUtils = oxUtils::getInstance();
00245                         $sCacheKey = 'fieldnames_' . $this->_sCoreTable . "_" . $this->_sCacheKey;
00246                         $aFieldNames = $myUtils->fromFileCache($sCacheKey);
00247                         $aFieldNames[$sFieldName] = $iFieldStatus;
00248                         $myUtils->toFileCache($sCacheKey, $aFieldNames);
00249                     }
00250                 } catch ( Exception $e ) {
00251                     return null;
00252                 }
00253 
00254                 //do not use field cache for this page
00255                 //as if we use it for lists then objects are loaded empty instead of lazy loading.
00256                 self::$_blDisableFieldCaching[get_class($this)] = true;
00257             }
00258 
00259             /*
00260             //save names to cache for next loading
00261             if ($this->_sCacheKey) {
00262                 $sCacheKey = 'fieldnames_' . $this->_sCoreTable . "_" . $this->_sCacheKey;
00263                 $aFieldNames = oxUtils::getInstance()->fromFileCache($sCacheKey);
00264                 $aFieldNames[$sFieldName] = $iFieldStatus;
00265                 oxUtils::getInstance()->toFileCache($sCacheKey, $aFieldNames);
00266             }*/
00267 
00268             oxUtilsObject::getInstance()->resetInstanceCache(get_class($this));
00269         }
00270 
00271         //returns oxStdClass implementing __toString() method due to uknown scenario where this var should be used.
00272         if (!isset( $this->$sName ) ) {
00273             $this->$sName = null;
00274         }
00275 
00276         return $this->$sName;
00277     }
00278 
00286     public function __isset($mVar)
00287     {
00288         return isset($this->$mVar);
00289     }
00290 
00296     public function __clone()
00297     {
00298         if (!$this->_blIsSimplyClonable) {
00299             foreach ( $this->_aFieldNames as $sField => $sVal ) {
00300                 $sLongName = $this->_getFieldLongName( $sField );
00301                 if ( is_object($this->$sLongName)) {
00302                     $this->$sLongName = clone $this->$sLongName;
00303                 }
00304             }
00305         }
00306     }
00307 
00315     public function oxClone($oObject)
00316     {
00317         $aClasVars = get_object_vars( $oObject);
00318         while (list($name, $value) = each($aClasVars)) {
00319             if ( is_object( $oObject->$name ) ) {
00320                 $this->$name = clone $oObject->$name;
00321             } else {
00322                 $this->$name = $oObject->$name;
00323             }
00324         }
00325     }
00326 
00335     public function init( $sTableName = null, $blForceAllFields = false)
00336     {
00337 
00338         if ( !$sTableName ) {
00339             $sTableName = $this->_sCoreTable;
00340         } else {
00341             $this->_sCoreTable = $sTableName;
00342         }
00343 
00344         // reset view table
00345         $this->_sViewTable = false;
00346 
00347         if ( count( $this->_aFieldNames ) <= 1 ) {
00348             $this->_initDataStructure( $blForceAllFields );
00349         }
00350     }
00351 
00359     public function assign( $dbRecord )
00360     {
00361         if ( !is_array( $dbRecord ) ) {
00362             return;
00363         }
00364 
00365 
00366         reset($dbRecord );
00367         while ( list( $sName, $sValue ) = each( $dbRecord ) ) {
00368 
00369             // patch for IIS
00370             //TODO: test it on IIS do we still need it
00371             //if( is_array($value) && count( $value) == 1)
00372             //    $value = current( $value);
00373 
00374             $this->_setFieldData( $sName, $sValue );
00375         }
00376 
00377         $sOxidField = $this->_getFieldLongName( 'oxid' );
00378         $this->_sOXID = $this->$sOxidField->value;
00379 
00380     }
00381 
00387     public function getClassName()
00388     {
00389         return $this->_sClassName;
00390     }
00391 
00397     public function getCoreTableName()
00398     {
00399         return $this->_sCoreTable;
00400     }
00401 
00407     public function getId()
00408     {
00409         return $this->_sOXID;
00410     }
00411 
00419     public function setId($sOXID = null)
00420     {
00421         if ( $sOXID ) {
00422             $this->_sOXID = $sOXID;
00423         } else {
00424             $this->_sOXID = oxUtilsObject::getInstance()->generateUID();
00425         }
00426 
00427         $sIdVarName = $this->_sCoreTable . "__oxid";
00428         $this->$sIdVarName = new oxField($this->_sOXID, oxField::T_RAW);
00429 
00430         return $this->_sOXID;
00431     }
00432 
00440     public function setShopId($iShopId)
00441     {
00442         $this->_iShopId = $iShopId;
00443     }
00444 
00450     public function getShopId()
00451     {
00452         return $this->_iShopId;
00453     }
00454 
00462     public function getViewName($blForceCoreTableUsage = null)
00463     {
00464         if (!$this->_sViewTable || ($blForceCoreTableUsage !== null)) {
00465             if ( ($blForceCoreTableUsage !== null)?$blForceCoreTableUsage:$this->_blForceCoreTableUsage ) {
00466                 $iShopId = -1;
00467             } else {
00468                 $iShopId = oxConfig::getInstance()->getShopId();
00469             }
00470             $sViewName = getViewName( $this->_sCoreTable, -1, $iShopId);
00471             if ($blForceCoreTableUsage !== null) {
00472                 return $sViewName;
00473             }
00474             $this->_sViewTable = $sViewName;
00475         }
00476         return $this->_sViewTable;
00477     }
00478 
00487     public function modifyCacheKey( $sCacheKey, $blOverride = false )
00488     {
00489         if ( $blOverride ) {
00490             $this->_sCacheKey = $sCacheKey;
00491         } else {
00492             $this->_sCacheKey .= $sCacheKey;
00493         }
00494     }
00495 
00501     public function disableLazyLoading()
00502     {
00503         $this->_blUseLazyLoading = false;
00504         $this->_initDataStructure(true);
00505     }
00506 
00507 
00513     public function isDerived()
00514     {
00515 
00516         return $this->_blIsDerived;
00517     }
00518 
00526     public function setIsDerived($blVal)
00527     {
00528         $this->_blIsDerived = $blVal;
00529     }
00530 
00537     public function isMultilang()
00538     {
00539         return false;
00540     }
00541 
00551     public function load( $sOXID)
00552     {
00553         /*
00554         if( !isset($oxID)){
00555             $oEx = oxNew('oxObjectException','core');
00556             $oEx->setMessage('EXCEPTION_OBJECT_OXIDNOTSET');
00557             $oEx->setObject($this);
00558             throw $oEx;
00559         }*/
00560 
00561         //getting at least one field before lazy loading the object
00562         $this->_addField('oxid', 0);
00563         $sSelect = $this->buildSelectString( array( $this->getViewName().".oxid" => $sOXID));
00564 
00565         return $this->_isLoaded = $this->assignRecord( $sSelect );
00566     }
00567 
00573     public function isLoaded()
00574     {
00575         return $this->_isLoaded;
00576     }
00577 
00585     public function buildSelectString( $aWhere = null)
00586     {
00587         $oDB = oxDb::getDb(true);
00588         $myUtils = oxUtils::getInstance();
00589 
00590         $sGet = $this->getSelectFields();
00591         $sSelect = "select $sGet from " . $this->getViewName() . " where 1 ";
00592 
00593         if ( $aWhere) {
00594             reset($aWhere);
00595             while (list($name, $value) = each($aWhere)) {
00596                 $sSelect .=  " and " . $name.' = '.$oDB->quote($value);
00597             }
00598         }
00599 
00600         // add active shop
00601 
00602         return $sSelect;
00603     }
00604 
00612     public function assignRecord( $sSelect)
00613     {
00614         $blRet = false;
00615 
00616         $oDB = oxDb::getDb(true);
00617 
00618         $rs = $oDB->execute( $sSelect);
00619         if ($rs != false && $rs->recordCount() > 0) {
00620             $blRet = true;
00621             $this->assign( $rs->fields);
00622         }
00623 
00624         return $blRet;
00625     }
00626 
00634     public function getFieldData( $sFieldName )
00635     {
00636         $sLongFieldName = $this->_getFieldLongName( $sFieldName );
00637             return $this->$sLongFieldName->value;
00638     }
00639 
00645     public function getSelectFields()
00646     {
00647         $aSelectFields = array();
00648 
00649         $sViewName = $this->getViewName();
00650 
00651         foreach ( $this->_aFieldNames as $sKey => $sField ) {
00652             $aSelectFields[] = $sViewName . '.' . $sKey;
00653         }
00654 
00655         $sSelectFields = join( ", ", $aSelectFields );
00656         return $sSelectFields;
00657     }
00658 
00666     public function delete( $sOXID = null)
00667     {
00668         if ( !$sOXID ) {
00669             $sOXID = $this->getId();
00670 
00671             //do not allow derived deletion
00672             if ( !$this->allowDerivedDelete() ) {
00673                 return false;
00674             }
00675         }
00676 
00677         if ( !$sOXID ) {
00678             return false;
00679         }
00680 
00681 
00682         $oDB = oxDb::getDb(true);
00683         $sDelete = "delete from $this->_sCoreTable where oxid = ".$oDB->quote( $sOXID );
00684         $rs = $oDB->execute( $sDelete );
00685         if ( $blDelete = ( bool ) $oDB->affected_Rows() ) {
00686             $this->onChange(ACTION_DELETE, $sOXID);
00687         }
00688 
00689         return $blDelete;
00690     }
00691 
00692 
00698     public function save()
00699     {
00700         if ( !is_array( $this->_aFieldNames ) ) {
00701             return false;
00702         }
00703 
00704         $blRet = false;
00705 
00706         // #739A - should be executed here because of date/time formatting feature
00707         if ( $this->isAdmin() && !$this->getConfig()->getConfigParam( 'blSkipFormatConversion' ) ) {
00708             foreach ($this->_aFieldNames as $sName => $sVal) {
00709                 $sLongName = $this->_getFieldLongName($sName);
00710                 if ( isset($this->$sLongName->fldtype) && $this->$sLongName->fldtype == "datetime" ) {
00711                     oxDb::getInstance()->convertDBDateTime( $this->$sLongName, true );
00712                 } elseif ( isset($this->$sLongName->fldtype) && $this->$sLongName->fldtype == "timestamp" ) {
00713                     oxDb::getInstance()->convertDBTimestamp( $this->$sLongName, true);
00714                 } elseif ( isset($this->$sLongName->fldtype) && $this->$sLongName->fldtype == "date" ) {
00715                     oxDb::getInstance()->convertDBDate( $this->$sLongName, true);
00716                 }
00717             }
00718         }
00719         if ( $this->exists() ) {
00720             //do not allow derived update
00721             if ( !$this->allowDerivedUpdate() ) {
00722                 return false;
00723             }
00724 
00725             $blRet = $this->_update();
00726             $sAction = ACTION_UPDATE;
00727         } else {
00728             $blRet = $this->_insert();
00729             $sAction = ACTION_INSERT;
00730         }
00731 
00732         $this->onChange($sAction);
00733 
00734         if ( $blRet ) {
00735             return $this->getId();
00736         } else {
00737             return false;
00738         }
00739     }
00740 
00746     public function allowDerivedUpdate()
00747     {
00748         return !$this->isDerived();
00749     }
00750 
00756     public function allowDerivedDelete()
00757     {
00758         return !$this->isDerived();
00759     }
00760 
00768     public function exists( $sOXID = null)
00769     {
00770         if ( !$sOXID ) {
00771             $sOXID = $this->getId();
00772         }
00773         if ( !$sOXID ) {
00774             return false;
00775         }
00776 
00777         $sViewName = $this->getCoreTableName();
00778         $oDB = oxDb::getDb( true );
00779         $sSelect= "select {$this->_sExistKey} from {$sViewName} where {$this->_sExistKey} = ".$oDB->quote( $sOXID );
00780 
00781         return ( bool ) $oDB->getOne( $sSelect );
00782     }
00783 
00791     public function getSqlActiveSnippet( $blForceCoreTable = null )
00792     {
00793         $sQ = '';
00794         $sTable = $this->getViewName($blForceCoreTable);
00795 
00796         // has 'active' field ?
00797         if ( isset( $this->_aFieldNames['oxactive'] ) ) {
00798             $sQ = " $sTable.oxactive = 1 ";
00799         }
00800 
00801         // has 'activefrom'/'activeto' fields ?
00802         if ( isset( $this->_aFieldNames['oxactivefrom'] ) && isset( $this->_aFieldNames['oxactiveto'] ) ) {
00803 
00804             $sDate = date( 'Y-m-d H:i:s', oxUtilsDate::getInstance()->getTime() );
00805 
00806             $sQ = $sQ?" $sQ or ":'';
00807             $sQ = " ( $sQ ( $sTable.oxactivefrom < '$sDate' and $sTable.oxactiveto > '$sDate' ) ) ";
00808         }
00809 
00810         return $sQ;
00811     }
00812 
00821     public function validate()
00822     {
00823         $this->_aErrors = array();
00824         foreach ($this->_aFieldNames as $fName => $iVal) {
00825 
00826             $fName = $this->_getFieldLongName($fName);
00827 
00828             if ( method_exists ( $this, "validate_$fName")) {
00829                 $validatorMethod = "validate_$fName";
00830                 if ( $error = $this->$validatorMethod()) {
00831                     $this->_aErrors[$fName] = $error;
00832                 }
00833             }
00834         }
00835         return !$this->hasErrors();
00836     }
00837 
00846     public function beforeUpdate( $sOXID = null )
00847     {
00848     }
00849 
00860     public function onChange( $iAction = null, $sOXID = null)
00861     {
00862     }
00863 
00864 
00872     public function hasErrors()
00873     {
00874         return count($this->_aErrors) > 0;
00875     }
00876 
00884     public function getErrors()
00885     {
00886         return $this->_aErrors;
00887     }
00888 
00898     public function getError( $sField)
00899     {
00900         if (isset($this->_aErrors[$sField])) {
00901             return $this->_aErrors[$sField];
00902         }
00903 
00904         //T2007-10-19
00905         //return array();
00906         return null;
00907     }
00908 
00918     public function getHtmlError( $sField)
00919     {
00920         if ( $error = $this->getError($sField) ) {
00921             return $error;
00922         }
00923     }
00924 
00930     public function setInList()
00931     {
00932         $this->_blIsInList = true;
00933     }
00934 
00940     protected function _isInList()
00941     {
00942         return $this->_blIsInList;
00943     }
00944 
00953     protected function _getObjectViewName( $sTable, $sShopID = null)
00954     {
00955         if ( $this->_blForceCoreTableUsage ) {
00956             $sShopID = -1;
00957         }
00958         return getViewName( $sTable, -1, $sShopID);
00959     }
00960 
00961 
00972     protected function _getTableFields($sTable, $blReturnSimple = false)
00973     {
00974         $myUtils = oxUtils::getInstance();
00975 
00976         $sCacheKey   = $sTable . "_allfields_" . $blReturnSimple;
00977         $aMetaFields = $myUtils->fromFileCache( $sCacheKey );
00978 
00979         if ( $aMetaFields ) {
00980             return $aMetaFields;
00981         }
00982 
00983         $aMetaFields = oxDb::getInstance()->getTableDescription( $sTable );
00984 
00985         if ( !$blReturnSimple ) {
00986             $myUtils->toFileCache( $sCacheKey, $aMetaFields );
00987             return $aMetaFields;
00988         }
00989 
00990         //returning simple array
00991         $aRet = array();
00992         if (is_array($aMetaFields)) {
00993             foreach ( $aMetaFields as $oVal ) {
00994                 $aRet[strtolower( $oVal->name )] = 0;
00995             }
00996         }
00997 
00998         $myUtils->toFileCache( $sCacheKey, $aRet);
00999 
01000         return $aRet;
01001     }
01002 
01014     protected function _getAllFields($blReturnSimple = false)
01015     {
01016         if (!$this->_sCoreTable) {
01017             return array();
01018         }
01019         return $this->_getTableFields($this->_sCoreTable, $blReturnSimple);
01020     }
01021 
01030     protected function _initDataStructure($blForceFullStructure = false)
01031     {
01032         $myUtils = oxUtils::getInstance();
01033 
01034         //get field names from cache
01035         $aFieldNames = null;
01036         $sFullCacheKey = 'fieldnames_' .$this->_sCoreTable . "_" . $this->_sCacheKey;
01037         if ($this->_sCacheKey && !$this->_isDisabledFieldCache()) {
01038             $aFieldNames = $myUtils->fromFileCache($sFullCacheKey);
01039         }
01040 
01041         if (!$aFieldNames) {
01042             $aFieldNames = $this->_getNonCachedFieldNames($blForceFullStructure);
01043             if ($this->_sCacheKey && !$this->_isDisabledFieldCache()) {
01044                 $myUtils->toFileCache($sFullCacheKey, $aFieldNames);
01045             }
01046         }
01047 
01048         if ( $aFieldNames !== false ) {
01049             foreach ( $aFieldNames as $sField => $sStatus ) {
01050                 $this->_addField($sField, $sStatus);
01051             }
01052         }
01053     }
01054 
01066     protected function _getNonCachedFieldNames($blForceFullStructure = false)
01067     {
01068         //T2008-02-22
01069         //so if this method is executed on cached version we see it when profiling
01070         startProfile("!__CACHABLE__!");
01071 
01072         //case 1. (admin)
01073         if ($this->isAdmin()) {
01074             $aMetaFields = $this->_getAllFields();
01075             foreach ( $aMetaFields as $oField ) {
01076                 if ( $oField->max_length == -1 ) {
01077                     $oField->max_length = 10;      // double or float
01078                 }
01079 
01080                 if ( $oField->type == "datetime" ) {
01081                     $oField->max_length = 20;
01082                 }
01083 
01084                 $this->_addField( $oField->name, $this->_getFieldStatus($oField->name), $oField->type, $oField->max_length );
01085             }
01086             stopProfile("!__CACHABLE__!");
01087             return false;
01088         }
01089 
01090         //case 2. (just get all fields)
01091         if ( $blForceFullStructure || !$this->_blUseLazyLoading ) {
01092             $aMetaFields = $this->_getAllFields(true);
01093             /*
01094             foreach ( $aMetaFields as $sFieldName => $sVal) {
01095                 $this->_addField( $sFieldName, $this->_getFieldStatus($sFieldName));
01096             }*/
01097             stopProfile("!__CACHABLE__!");
01098             return $aMetaFields;
01099         }
01100 
01101         //case 3. (get only oxid field, so we can fetch the rest of the fields over lazy loading mechanism)
01102         stopProfile("!__CACHABLE__!");
01103         return array("oxid" => 0);
01104     }
01105 
01114     protected function _getFieldStatus( $sFieldName )
01115     {
01116         return 0;
01117     }
01118 
01129     protected function _addField($sName, $iStatus, $sType = null, $sLength = null)
01130     {
01131         //preparation
01132         $sName = strtolower( $sName );
01133 
01134         //adding field names element
01135         $this->_aFieldNames[$sName] = $iStatus;
01136 
01137         //allready set?
01138         $sLongName = $this->_getFieldLongName($sName);
01139         if ( isset($this->$sLongName) ) {
01140             return;
01141         }
01142 
01143         //defining the field
01144         $oField = false;
01145 
01146         if ( isset( $sType ) ) {
01147             $oField = new oxField();
01148             $oField->fldtype = $sType;
01149             //T2008-01-29
01150             //can't clone as the fields are objects and are not fully cloned
01151             $this->_blIsSimplyClonable = false;
01152         }
01153 
01154         if ( isset( $sLength ) ) {
01155             if ( !$oField ) {
01156                 $oField = new oxField();
01157             }
01158             $oField->fldmax_length = $sLength;
01159             $this->_blIsSimplyClonable = false;
01160         }
01161 
01162         $this->$sLongName = $oField;
01163     }
01164 
01172     protected function _getFieldLongName( $sFieldName )
01173     {
01174         //trying to avoid strpos call as often as possible
01175         if ( $sFieldName[2] == $this->_sCoreTable[2] && strpos( $sFieldName, $this->_sCoreTable . "__" ) === 0 ) {
01176             return $sFieldName;
01177         }
01178 
01179         return $this->_sCoreTable . "__" . strtolower( $sFieldName );
01180     }
01181 
01191     protected function _setFieldData( $sFieldName, $sValue, $iDataType = oxField::T_TEXT)
01192     {
01193 
01194         $sLongFieldName = $this->_getFieldLongName( $sFieldName);
01195         //$sLongFieldName = $this->_sCoreTable . "__" . strtolower($sFieldName);
01196 
01197         //T2008-03-14
01198         //doing this because in lazy loaded lists on first load it is harmful to have initilised fields but not yet set
01199         //situation: only first article is loaded fully for "select oxid from oxarticles"
01200         /*
01201         if ($this->_blUseLazyLoading && !isset($this->$sLongFieldName))
01202             return;*/
01203 
01204         //in non lazy loading case we just add a field and do not care about it more
01205         if (!$this->_blUseLazyLoading && !isset($this->$sLongFieldName)) {
01206             $aFields = $this->_getAllFields(true);
01207             if ( isset( $aFields[strtolower($sFieldName)] ) ) {
01208                 $this->_addField($sFieldName, $this->_getFieldStatus($sFieldName));
01209             }
01210         }
01211         // if we have a double field we replace "," with "." in case somebody enters it in european format
01212         if (isset($this->$sLongFieldName) && isset($this->$sLongFieldName->fldtype) && $this->$sLongFieldName->fldtype == "double") {
01213             $sValue = str_replace( ",", ".", $sValue );
01214         }
01215 
01216         // isset is REQUIRED here not to use getter
01217         if (isset($this->$sLongFieldName) && is_object($this->$sLongFieldName)) {
01218             $this->$sLongFieldName->setValue($sValue, $iDataType);
01219         } else {
01220             $this->$sLongFieldName = new oxField($sValue, $iDataType);
01221         }
01222 
01223     }
01224 
01232     protected function _canFieldBeNull( $sFieldName )
01233     {
01234         $aMetaData = $this->_getAllFields();
01235         foreach ( $aMetaData as $oMetaInfo ) {
01236             if ( strcasecmp( $oMetaInfo->name, $sFieldName ) == 0 ) {
01237                 return !$oMetaInfo->not_null;
01238             }
01239         }
01240         return false;
01241     }
01242 
01251     protected function _getUpdateFieldValue( $sFieldName, $oField )
01252     {
01253         if ( $oField instanceof oxField ) {
01254             $mValue = $oField->getRawValue();
01255         } else {
01256             $mValue = $oField->value;
01257         }
01258         // Sarunas. check if this field value is null AND it can be null according to table description
01259         if ( ( null === $mValue ) && $this->_canFieldBeNull( $sFieldName ) ) {
01260             return 'null';
01261         }
01262         return oxDb::getDb()->quote( $mValue );
01263     }
01264 
01273     protected function _getUpdateFields( $blUseSkipSaveFields = true )
01274     {
01275         $sSql = '';
01276         $blSep  = false;
01277 
01278         foreach (array_keys($this->_aFieldNames) as $sKey) {
01279             $sLongName = $this->_getFieldLongName($sKey);
01280             $oField = $this->$sLongName;
01281 
01282 
01283             if ( !$blUseSkipSaveFields || ($blUseSkipSaveFields && !in_array(strtolower($sKey), $this->_aSkipSaveFields)) ) {
01284                 $sSql .= (( $blSep) ? ',':'' ).$sKey." = ".$this->_getUpdateFieldValue($sKey, $oField);
01285                 $blSep = true;
01286             }
01287         }
01288 
01289         return $sSql;
01290     }
01291 
01301     protected function _update()
01302     {
01303         //do not allow derived item update
01304         if ( !$this->allowDerivedUpdate() ) {
01305             return false;
01306         }
01307 
01308 
01309         if ( !$this->getId() ) {
01310             $oEx = oxNew( 'oxObjectException' );
01311             $oEx->setMessage( 'EXCEPTION_OBJECT_OXIDNOTSET' );
01312             $oEx->setObject($this);
01313             throw $oEx;
01314         }
01315 
01316         $sIDKey = oxUtils::getInstance()->getArrFldName( $this->_sCoreTable.".oxid");
01317         $this->$sIDKey = new oxField($this->getId(), oxField::T_RAW);
01318         $oDb = oxDB::getDb();
01319 
01320         $sUpdate= "update {$this->_sCoreTable} set ".$this->_getUpdateFields()
01321                  ." where {$this->_sCoreTable}.oxid = ".$oDb->quote( $this->getId() );
01322 
01323         //trigger event
01324         $this->beforeUpdate();
01325 
01326         $blRet = (bool) $oDb->execute( $sUpdate);
01327         $this->_rebuildCache();
01328 
01329         return $blRet;
01330     }
01331 
01339     protected function _insert()
01340     {
01341 
01342         $oDB      = oxDb::getDb(true);
01343         $myConfig = $this->getConfig();
01344         $myUtils  = oxUtils::getInstance();
01345 
01346         // let's get a new ID
01347         if ( !$this->getId()) {
01348             $this->setId();
01349         }
01350 
01351         $sIDKey = $myUtils->getArrFldName( $this->_sCoreTable.".oxid");
01352         $this->$sIDKey = new oxField($this->getId(), oxField::T_RAW);
01353         $sInsert= "Insert into {$this->_sCoreTable} set ";
01354 
01355         //setting oxshopid
01356         $sShopField = $myUtils->getArrFldName($this->_sCoreTable.".oxshopid");
01357         if (isset($this->$sShopField) && !$this->$sShopField->value)
01358             $this->$sShopField = new oxField($myConfig->getShopId(), oxField::T_RAW);
01359 
01360         $sInsert .= $this->_getUpdateFields( false );
01361         $blRet = (bool) $oDB->execute( $sInsert);
01362 
01363         $this->_rebuildCache();
01364 
01365         return $blRet;
01366 
01367     }
01368 
01374     protected function _rebuildCache()
01375     {
01376         if ( !$this->_blIsNewCache) {
01377             oxUtils::getInstance()->rebuildCache();
01378             $this->_blIsNewCache = true;
01379         }
01380     }
01381 
01391     protected function _setRecordNumber( $sMaxField, $aWhere = null, $iMaxTryCnt = 5 )
01392     {
01393         // filtering
01394         $sWhere = "";
01395         if ( is_array( $aWhere ) && count( $aWhere ) > 0) {
01396             $sWhere = implode(" and ", $aWhere).' and ';
01397         }
01398         $oDb = oxDb::getDb(true);
01399 
01400         // SQL to set record number
01401         $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() );
01402 
01403         // SQL to check record number dublicates
01404         //this should not happen normally but we prefer to take extra care in this case due to parallel script execution etc.
01405         $sMaxSelect = "select $sMaxField from ".$this->getViewName()." where oxid=".$oDb->quote( $this->getId() );
01406         $sCheck = "select count(oxid) from ".$this->getViewName()." where $sMaxField = ($sMaxSelect) and $sWhere 1 ";
01407 
01408         do {
01409             if ( $oDb->execute( $sUpdate ) === false ) {
01410                 return false;
01411             }
01412 
01413             $iChkCnt = $oDb->getOne( $sCheck );
01414         } while ( ( $iChkCnt > 1 ) && $iMaxTryCnt-- );
01415 
01416         $sFieldName = $this->getViewName().'__'.$sMaxField;
01417         $this->$sFieldName = new oxField( $oDb->getOne( $sMaxSelect ), oxField::T_RAW);//int value
01418 
01419         return ( $iChkCnt == 1 );
01420     }
01421 
01428     protected function _isDisabledFieldCache()
01429     {
01430         $sClass = get_class($this);
01431         if (isset(self::$_blDisableFieldCaching[$sClass]) && self::$_blDisableFieldCaching[$sClass]) {
01432             return true;
01433         }
01434 
01435         return false;
01436     }
01437 
01443     public function isOx()
01444     {
01445         $sOxId = $this->getId();
01446         if ( $sOxId[0] == 'o' && $sOxId[1] == 'x' ) {
01447             return true;
01448         }
01449         return false;
01450     }
01451 
01457     public function isReadOnly()
01458     {
01459         return $this->_blReadOnly;
01460     }
01461 
01469     public function setReadOnly( $blReadOnly )
01470     {
01471         $this->_blReadOnly = $blReadOnly;
01472     }
01473 
01479     public function getFieldNames()
01480     {
01481         return array_keys( $this->_aFieldNames );
01482     }
01483 }