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 {
00018 
00024     protected $_sOXID = null;
00025 
00031     protected $_iShopId = null;
00032 
00038     protected $_blIsSimplyClonable = true;
00039 
00045     protected $_sClassName = 'oxbase';
00046 
00052     protected $_sCoreTable = null;
00053 
00059     protected $_sViewTable = null;
00060 
00061 
00067     protected $_aFieldNames = array('oxid' => 0);
00068 
00074     protected $_sCacheKey = null;
00075 
00081     protected $_blUseLazyLoading = false;
00082 
00088     protected $_aSkipSaveFields = array('oxtimestamp');
00089 
00095     protected $_blUseSkipSaveFields = true;
00096 
00102     protected $_sExistKey = 'oxid';
00103 
00110     protected $_blIsDerived = null;
00111 
00121     protected static $_blDisableFieldCaching = array();
00122 
00128     protected $_blIsSeoObject = false;
00129 
00135     protected $_blUpdateSeo = true;
00136 
00142     protected $_blReadOnly = false;
00143 
00149     protected $_blIsInList = false;
00150 
00156     protected $_isLoaded = false;
00157 
00163     protected $_aInnerLazyCache = null;
00164 
00170     protected $_blEmployMultilanguage = false;
00171 
00172 
00178     public function getUseSkipSaveFields()
00179     {
00180         return $this->_blUseSkipSaveFields;
00181     }
00182 
00188     public function setUseSkipSaveFields($blUseSkipSaveFields)
00189     {
00190         $this->_blUseSkipSaveFields = $blUseSkipSaveFields;
00191     }
00192 
00196     public function __construct()
00197     {
00198         // set active shop
00199         $myConfig = $this->getConfig();
00200         $this->_sCacheKey = $this->getViewName();
00201 
00202         $this->_addSkippedSaveFieldsForMapping();
00203         $this->_disableLazyLoadingForCaching();
00204 
00205         if ($this->_blUseLazyLoading) {
00206             $this->_sCacheKey .= $myConfig->getActiveView()->getClassName();
00207         } else {
00208             $this->_sCacheKey .= 'allviews';
00209         }
00210 
00211         //do not cache for admin?
00212         if ($this->isAdmin()) {
00213             $this->_sCacheKey = null;
00214         }
00215 
00216         $this->setShopId($myConfig->getShopId());
00217     }
00218 
00225     public function __set($sName, $sValue)
00226     {
00227         $this->$sName = $sValue;
00228         if ($this->_blUseLazyLoading && strpos($sName, $this->_sCoreTable . '__') === 0) {
00229             $sFieldName = str_replace($this->_sCoreTable . "__", '', $sName);
00230             if ($sFieldName != 'oxnid' && (!isset($this->_aFieldNames[$sFieldName]) || !$this->_aFieldNames[$sFieldName])) {
00231                 $aAllFields = $this->_getAllFields(true);
00232                 if (isset($aAllFields[strtolower($sFieldName)])) {
00233                     $iFieldStatus = $this->_getFieldStatus($sFieldName);
00234                     $this->_addField($sFieldName, $iFieldStatus);
00235                 }
00236             }
00237         }
00238     }
00239 
00247     public function __get($sName)
00248     {
00249         switch ($sName) {
00250             case 'blIsDerived':
00251                 return $this->isDerived();
00252                 break;
00253             case 'sOXID':
00254                 return $this->getId();
00255                 break;
00256             case 'blReadOnly':
00257                 return $this->isReadOnly();
00258                 break;
00259         }
00260 
00261         // implementing lazy loading fields
00262         // This part of the code is slow and normally is called before field cache is built.
00263         // Make sure it is not called after first page is loaded and cache data is fully built.
00264         if ($this->_blUseLazyLoading && stripos($sName, $this->_sCoreTable . "__") === 0) {
00265 
00266             if ($this->getId()) {
00267 
00268                 //lazy load it
00269                 $sFieldName = str_replace($this->_sCoreTable . '__', '', $sName);
00270                 $sCacheFieldName = strtoupper($sFieldName);
00271 
00272                 $iFieldStatus = $this->_getFieldStatus($sFieldName);
00273                 $sViewName = $this->getViewName();
00274                 $sId = $this->getId();
00275 
00276                 try {
00277                     if ($this->_aInnerLazyCache === null) {
00278 
00279                         $oDb = oxDb::getDb(oxDb::FETCH_MODE_ASSOC);
00280                         $sQ = 'SELECT * FROM ' . $sViewName . ' WHERE `oxid` = ' . $oDb->quote($sId);
00281                         $rs = $oDb->select($sQ);
00282                         if ($rs && $rs->RecordCount()) {
00283                             $this->_aInnerLazyCache = array_change_key_case($rs->fields, CASE_UPPER);
00284                             if (array_key_exists($sCacheFieldName, $this->_aInnerLazyCache)) {
00285                                 $sFieldValue = $this->_aInnerLazyCache[$sCacheFieldName];
00286                             } else {
00287                                 return null;
00288                             }
00289                         } else {
00290                             return null;
00291                         }
00292                     } elseif (array_key_exists($sCacheFieldName, $this->_aInnerLazyCache)) {
00293                         $sFieldValue = $this->_aInnerLazyCache[$sCacheFieldName];
00294                     } else {
00295                         return null;
00296                     }
00297 
00298                     $this->_addField($sFieldName, $iFieldStatus);
00299                     $this->_setFieldData($sFieldName, $sFieldValue);
00300 
00301                     //save names to cache for next loading
00302                     if ($this->_sCacheKey) {
00303                         $myUtils = oxRegistry::getUtils();
00304                         $sCacheKey = 'fieldnames_' . $this->_sCoreTable . '_' . $this->_sCacheKey;
00305                         $aFieldNames = $myUtils->fromFileCache($sCacheKey);
00306                         $aFieldNames[$sFieldName] = $iFieldStatus;
00307                         $myUtils->toFileCache($sCacheKey, $aFieldNames);
00308                     }
00309                 } catch (Exception $e) {
00310                     return null;
00311                 }
00312 
00313                 //do not use field cache for this page
00314                 //as if we use it for lists then objects are loaded empty instead of lazy loading.
00315                 self::$_blDisableFieldCaching[get_class($this)] = true;
00316             }
00317 
00318             oxUtilsObject::getInstance()->resetInstanceCache(get_class($this));
00319         }
00320 
00321         //returns stdClass implementing __toString() method due to uknown scenario where this var should be used.
00322         if (!isset($this->$sName)) {
00323             $this->$sName = null;
00324         }
00325 
00326         return $this->$sName;
00327     }
00328 
00336     public function __isset($mVar)
00337     {
00338         return isset($this->$mVar);
00339     }
00340 
00344     public function __clone()
00345     {
00346         if (!$this->_blIsSimplyClonable) {
00347             foreach ($this->_aFieldNames as $sField => $sVal) {
00348                 $sLongName = $this->_getFieldLongName($sField);
00349                 if (is_object($this->$sLongName)) {
00350                     $this->$sLongName = clone $this->$sLongName;
00351                 }
00352             }
00353         }
00354     }
00355 
00361     public function oxClone($oObject)
00362     {
00363         $aClasVars = get_object_vars($oObject);
00364         while (list($name, $value) = each($aClasVars)) {
00365             if (is_object($oObject->$name)) {
00366                 $this->$name = clone $oObject->$name;
00367             } else {
00368                 $this->$name = $oObject->$name;
00369             }
00370         }
00371     }
00372 
00378     public function getUpdateSeo()
00379     {
00380         return $this->_blUpdateSeo;
00381     }
00382 
00388     public function setUpdateSeo($blUpdateSeo)
00389     {
00390         $this->_blUpdateSeo = $blUpdateSeo;
00391     }
00392 
00400     protected function _setUpdateSeoOnFieldChange($sField)
00401     {
00402         if ($this->getId() && in_array($sField, $this->getFieldNames())) {
00403             $oDb = oxDb::getDb();
00404             $sTableName = $this->getCoreTableName();
00405             $sQuotedOxid = $oDb->quote($this->getId());
00406             $sTitle = $oDb->getOne("select `{$sField}` from `{$sTableName}` where `oxid` = {$sQuotedOxid}");
00407             $sFieldValue = "{$sTableName}__{$sField}";
00408             $sCurrentTitle = $this->$sFieldValue->value;
00409 
00410             if ($sTitle == $sCurrentTitle) {
00411                 $this->setUpdateSeo(false);
00412             }
00413         }
00414     }
00415 
00422     public function init($sTableName = null, $blForceAllFields = false)
00423     {
00424         if ($sTableName) {
00425             $this->_sCoreTable = $sTableName;
00426         }
00427 
00428         // reset view table
00429         $this->_sViewTable = false;
00430 
00431         if (count($this->_aFieldNames) <= 1) {
00432             $this->_initDataStructure($blForceAllFields);
00433         }
00434     }
00435 
00443     public function assign($dbRecord)
00444     {
00445         if (!is_array($dbRecord)) {
00446             return;
00447         }
00448 
00449 
00450         reset($dbRecord);
00451         while (list($sName, $sValue) = each($dbRecord)) {
00452 
00453             // patch for IIS
00454             //TODO: test it on IIS do we still need it
00455             //if( is_array($value) && count( $value) == 1)
00456             //    $value = current( $value);
00457 
00458             $this->_setFieldData($sName, $sValue);
00459         }
00460 
00461         $sOxidField = $this->_getFieldLongName('oxid');
00462         $this->_sOXID = $this->$sOxidField->value;
00463 
00464     }
00465 
00471     public function getClassName()
00472     {
00473         return $this->_sClassName;
00474     }
00475 
00481     public function getCoreTableName()
00482     {
00483         return $this->_sCoreTable;
00484     }
00485 
00491     public function getId()
00492     {
00493         return $this->_sOXID;
00494     }
00495 
00503     public function setId($sOXID = null)
00504     {
00505         if ($sOXID) {
00506             $this->_sOXID = $sOXID;
00507         } else {
00508             if ($this->getCoreTableName() == 'oxobject2category') {
00509                 $sObjectId = $this->oxobject2category__oxobjectid;
00510                 $sCatId = $this->oxobject2category__oxcatnid;
00511                 $sShopID = $this->oxobject2category__oxshopid;
00512                 $this->_sOXID = md5($sObjectId . $sCatId . $sShopID);
00513             } else {
00514                 $this->_sOXID = oxUtilsObject::getInstance()->generateUID();
00515             }
00516         }
00517 
00518         $sIdVarName = $this->getCoreTableName() . '__oxid';
00519         $this->$sIdVarName = new oxField($this->_sOXID, oxField::T_RAW);
00520 
00521         return $this->_sOXID;
00522     }
00523 
00529     public function setShopId($iShopId)
00530     {
00531         $this->_iShopId = $iShopId;
00532     }
00533 
00539     public function getShopId()
00540     {
00541         return $this->_iShopId;
00542     }
00543 
00551     public function getViewName($blForceCoreTableUsage = null)
00552     {
00553         if (!$this->_sViewTable || ($blForceCoreTableUsage !== null)) {
00554             if ($blForceCoreTableUsage === true) {
00555                 return $this->getCoreTableName();
00556             }
00557 
00558 
00559             if (($blForceCoreTableUsage !== null) && $blForceCoreTableUsage) {
00560                 $iShopId = -1;
00561             } else {
00562                 $iShopId = oxRegistry::getConfig()->getShopId();
00563             }
00564 
00565             $sViewName = getViewName($this->getCoreTableName(), $this->_blEmployMultilanguage == false ? -1 : $this->getLanguage(), $iShopId);
00566             if ($blForceCoreTableUsage !== null) {
00567                 return $sViewName;
00568             }
00569             $this->_sViewTable = $sViewName;
00570         }
00571 
00572         return $this->_sViewTable;
00573     }
00574 
00581     public function modifyCacheKey($sCacheKey, $blOverride = false)
00582     {
00583         if ($blOverride) {
00584             $this->_sCacheKey = $sCacheKey;
00585         } else {
00586             $this->_sCacheKey .= $sCacheKey;
00587         }
00588     }
00589 
00593     public function disableLazyLoading()
00594     {
00595         $this->_blUseLazyLoading = false;
00596         $this->_initDataStructure(true);
00597     }
00598 
00599 
00605     public function isDerived()
00606     {
00607 
00608         return $this->_blIsDerived;
00609     }
00610 
00616     public function setIsDerived($blVal)
00617     {
00618         $this->_blIsDerived = $blVal;
00619     }
00620 
00627     public function isMultilang()
00628     {
00629         return false;
00630     }
00631 
00641     public function load($sOXID)
00642     {
00643 
00644         //getting at least one field before lazy loading the object
00645         $this->_addField('oxid', 0);
00646         $sSelect = $this->buildSelectString(array($this->getViewName() . '.oxid' => $sOXID));
00647         $this->_isLoaded = $this->assignRecord($sSelect);
00648 
00649 
00650         return $this->_isLoaded;
00651     }
00652 
00653 
00659     public function isLoaded()
00660     {
00661         return $this->_isLoaded;
00662     }
00663 
00671     public function buildSelectString($aWhere = null)
00672     {
00673         $oDB = oxDb::getDb();
00674 
00675         $sGet = $this->getSelectFields();
00676         $sSelect = "select $sGet from " . $this->getViewName() . ' where 1 ';
00677 
00678         if ($aWhere) {
00679             reset($aWhere);
00680             while (list($name, $value) = each($aWhere)) {
00681                 $sSelect .= ' and ' . $name . ' = ' . $oDB->quote($value);
00682             }
00683         }
00684 
00685         // add active shop
00686 
00687         return $sSelect;
00688     }
00689 
00697     public function assignRecord($sSelect)
00698     {
00699         $blRet = false;
00700 
00701         $rs = oxDb::getDb(oxDb::FETCH_MODE_ASSOC)->select($sSelect);
00702 
00703         if ($rs != false && $rs->recordCount() > 0) {
00704             $blRet = true;
00705             $this->assign($rs->fields);
00706         }
00707 
00708         return $blRet;
00709     }
00710 
00718     public function getFieldData($sFieldName)
00719     {
00720         $sLongFieldName = $this->_getFieldLongName($sFieldName);
00721 
00722         return $this->$sLongFieldName->value;
00723     }
00724 
00732     public function getSelectFields($blForceCoreTableUsage = null)
00733     {
00734         $aSelectFields = array();
00735 
00736         $sViewName = $this->getViewName($blForceCoreTableUsage);
00737 
00738         foreach ($this->_aFieldNames as $sKey => $sField) {
00739             if ($sViewName) {
00740                 $aSelectFields[] = "`$sViewName`.`$sKey`";
00741             } else {
00742                 $aSelectFields[] = ".`$sKey`";
00743             }
00744 
00745         }
00746 
00747         $sSelectFields = join(', ', $aSelectFields);
00748 
00749         return $sSelectFields;
00750     }
00751 
00759     public function delete($sOxId = null)
00760     {
00761         if (!$sOxId) {
00762             $sOxId = $this->getId();
00763 
00764             //do not allow derived deletion
00765             if (!$this->allowDerivedDelete()) {
00766                 return false;
00767             }
00768         }
00769 
00770         if (!$sOxId) {
00771             return false;
00772         }
00773 
00774 
00775         $this->_removeElement2ShopRelations($sOxId);
00776 
00777         $oDB = oxDb::getDb(oxDb::FETCH_MODE_ASSOC);
00778         $sCoreTable = $this->getCoreTableName();
00779         $sDelete = "delete from {$sCoreTable} where oxid = " . $oDB->quote($sOxId);
00780         $oDB->execute($sDelete);
00781         if ($blDelete = (bool) $oDB->affected_Rows()) {
00782             $this->onChange(ACTION_DELETE, $sOxId);
00783         }
00784 
00785         return $blDelete;
00786     }
00787 
00793     protected function _removeElement2ShopRelations($sOxId)
00794     {
00795     }
00796 
00797 
00803     public function save()
00804     {
00805         if (!is_array($this->_aFieldNames)) {
00806             return false;
00807         }
00808 
00809         // #739A - should be executed here because of date/time formatting feature
00810         if ($this->isAdmin() && !$this->getConfig()->getConfigParam('blSkipFormatConversion')) {
00811             foreach ($this->_aFieldNames as $sName => $sVal) {
00812                 $sLongName = $this->_getFieldLongName($sName);
00813                 if (isset($this->$sLongName->fldtype) && $this->$sLongName->fldtype == 'datetime') {
00814                     oxRegistry::get('oxUtilsDate')->convertDBDateTime($this->$sLongName, true);
00815                 } elseif (isset($this->$sLongName->fldtype) && $this->$sLongName->fldtype == 'timestamp') {
00816                     oxRegistry::get('oxUtilsDate')->convertDBTimestamp($this->$sLongName, true);
00817                 } elseif (isset($this->$sLongName->fldtype) && $this->$sLongName->fldtype == 'date') {
00818                     oxRegistry::get('oxUtilsDate')->convertDBDate($this->$sLongName, true);
00819                 }
00820             }
00821         }
00822 
00823         if ($this->exists()) {
00824             //do not allow derived update
00825             if (!$this->allowDerivedUpdate()) {
00826                 return false;
00827             }
00828 
00829             $blRet = $this->_update();
00830             $sAction = ACTION_UPDATE;
00831         } else {
00832             $blRet = $this->_insert();
00833             $sAction = ACTION_INSERT;
00834         }
00835 
00836         $this->onChange($sAction);
00837 
00838         if ($blRet) {
00839             return $this->getId();
00840         } else {
00841             return false;
00842         }
00843     }
00844 
00850     public function allowDerivedUpdate()
00851     {
00852         return !$this->isDerived();
00853     }
00854 
00860     public function allowDerivedDelete()
00861     {
00862         return !$this->isDerived();
00863     }
00864 
00872     public function exists($sOXID = null)
00873     {
00874         if (!$sOXID) {
00875             $sOXID = $this->getId();
00876         }
00877         if (!$sOXID) {
00878             return false;
00879         }
00880 
00881         $sViewName = $this->getCoreTableName();
00882         $oDb = oxDb::getDb(oxDb::FETCH_MODE_ASSOC);
00883         $sSelect = "select {$this->_sExistKey} from {$sViewName} where {$this->_sExistKey} = " . $oDb->quote($sOXID);
00884 
00885         return ( bool ) $oDb->getOne($sSelect, false, false);
00886     }
00887 
00895     public function getSqlActiveSnippet($blForceCoreTable = null)
00896     {
00897         $sQ = '';
00898         $sTable = $this->getViewName($blForceCoreTable);
00899 
00900         // has 'active' field ?
00901         if (isset($this->_aFieldNames['oxactive'])) {
00902             $sQ = " $sTable.oxactive = 1 ";
00903         }
00904 
00905         // has 'activefrom'/'activeto' fields ?
00906         if (isset($this->_aFieldNames['oxactivefrom']) && isset($this->_aFieldNames['oxactiveto'])) {
00907 
00908             $sDate = date('Y-m-d H:i:s', oxRegistry::get('oxUtilsDate')->getTime());
00909 
00910             $sQ = $sQ ? " $sQ or " : '';
00911             $sQ = " ( $sQ ( $sTable.oxactivefrom < '$sDate' and $sTable.oxactiveto > '$sDate' ) ) ";
00912         }
00913 
00914         return $sQ;
00915     }
00916 
00923     public function beforeUpdate($sOXID = null)
00924     {
00925     }
00926 
00935     public function onChange($iAction = null, $sOXID = null)
00936     {
00937     }
00938 
00939 
00943     public function setInList()
00944     {
00945         $this->_blIsInList = true;
00946     }
00947 
00953     protected function _isInList()
00954     {
00955         return $this->_blIsInList;
00956     }
00957 
00966     protected function _getObjectViewName($sTable, $sShopID = null)
00967     {
00968 
00969         return getViewName($sTable, -1, $sShopID);
00970     }
00971 
00972 
00983     protected function _getTableFields($sTable, $blReturnSimple = false)
00984     {
00985         $myUtils = oxRegistry::getUtils();
00986 
00987         $sCacheKey = $sTable . '_allfields_' . $blReturnSimple;
00988         $aMetaFields = $myUtils->fromFileCache($sCacheKey);
00989 
00990         if ($aMetaFields) {
00991             return $aMetaFields;
00992         }
00993 
00994         $aMetaFields = oxDb::getInstance()->getTableDescription($sTable);
00995 
00996         if (!$blReturnSimple) {
00997             $myUtils->toFileCache($sCacheKey, $aMetaFields);
00998 
00999             return $aMetaFields;
01000         }
01001 
01002         //returning simple array
01003         $aRet = array();
01004         if (is_array($aMetaFields)) {
01005             foreach ($aMetaFields as $oVal) {
01006                 $aRet[strtolower($oVal->name)] = 0;
01007             }
01008         }
01009 
01010         $myUtils->toFileCache($sCacheKey, $aRet);
01011 
01012         return $aRet;
01013     }
01014 
01026     protected function _getAllFields($blReturnSimple = false)
01027     {
01028         if (!$this->getCoreTableName()) {
01029             return array();
01030         }
01031 
01032         return $this->_getTableFields($this->getCoreTableName(), $blReturnSimple);
01033     }
01034 
01041     protected function _initDataStructure($blForceFullStructure = false)
01042     {
01043         $myUtils = oxRegistry::getUtils();
01044 
01045         //get field names from cache
01046         $aFieldNames = null;
01047         $sFullCacheKey = 'fieldnames_' . $this->getCoreTableName() . '_' . $this->_sCacheKey;
01048         if ($this->_sCacheKey && !$this->_isDisabledFieldCache()) {
01049             $aFieldNames = $myUtils->fromFileCache($sFullCacheKey);
01050         }
01051 
01052         if (!$aFieldNames) {
01053             $aFieldNames = $this->_getNonCachedFieldNames($blForceFullStructure);
01054             if ($this->_sCacheKey && !$this->_isDisabledFieldCache()) {
01055                 $myUtils->toFileCache($sFullCacheKey, $aFieldNames);
01056             }
01057         }
01058 
01059         if ($aFieldNames !== false) {
01060             foreach ($aFieldNames as $sField => $sStatus) {
01061                 $this->_addField($sField, $sStatus);
01062             }
01063         }
01064     }
01065 
01077     protected function _getNonCachedFieldNames($blForceFullStructure = false)
01078     {
01079         //T2008-02-22
01080         //so if this method is executed on cached version we see it when profiling
01081         startProfile('!__CACHABLE__!');
01082 
01083         //case 1. (admin)
01084         if ($this->isAdmin()) {
01085             $aMetaFields = $this->_getAllFields();
01086             foreach ($aMetaFields as $oField) {
01087                 if ($oField->max_length == -1) {
01088                     $oField->max_length = 10; // double or float
01089                 }
01090 
01091                 if ($oField->type == 'datetime') {
01092                     $oField->max_length = 20;
01093                 }
01094 
01095                 $this->_addField($oField->name, $this->_getFieldStatus($oField->name), $oField->type, $oField->max_length);
01096             }
01097             stopProfile('!__CACHABLE__!');
01098 
01099             return false;
01100         }
01101 
01102         //case 2. (just get all fields)
01103         if ($blForceFullStructure || !$this->_blUseLazyLoading) {
01104             $aMetaFields = $this->_getAllFields(true);
01105             /*
01106             foreach ( $aMetaFields as $sFieldName => $sVal) {
01107                 $this->_addField( $sFieldName, $this->_getFieldStatus($sFieldName));
01108             }*/
01109             stopProfile('!__CACHABLE__!');
01110 
01111             return $aMetaFields;
01112         }
01113 
01114         //case 3. (get only oxid field, so we can fetch the rest of the fields over lazy loading mechanism)
01115         stopProfile('!__CACHABLE__!');
01116 
01117         return array('oxid' => 0);
01118     }
01119 
01128     protected function _getFieldStatus($sFieldName)
01129     {
01130         return 0;
01131     }
01132 
01143     protected function _addField($sName, $iStatus, $sType = null, $sLength = null)
01144     {
01145         //preparation
01146         $sName = strtolower($sName);
01147 
01148         //adding field names element
01149         $this->_aFieldNames[$sName] = $iStatus;
01150 
01151         //already set?
01152         $sLongName = $this->_getFieldLongName($sName);
01153         if (isset($this->$sLongName)) {
01154             return;
01155         }
01156 
01157         //defining the field
01158         $oField = false;
01159 
01160         if (isset($sType)) {
01161             $oField = new oxField();
01162             $oField->fldtype = $sType;
01163             //T2008-01-29
01164             //can't clone as the fields are objects and are not fully cloned
01165             $this->_blIsSimplyClonable = false;
01166         }
01167 
01168         if (isset($sLength)) {
01169             if (!$oField) {
01170                 $oField = new oxField();
01171             }
01172             $oField->fldmax_length = $sLength;
01173             $this->_blIsSimplyClonable = false;
01174         }
01175 
01176         $this->$sLongName = $oField;
01177     }
01178 
01186     protected function _getFieldLongName($sFieldName)
01187     {
01188         //trying to avoid strpos call as often as possible
01189         $sCoreTableName = $this->getCoreTableName();
01190         if ($sFieldName[2] == $sCoreTableName[2] && strpos($sFieldName, $sCoreTableName . '__') === 0) {
01191             return $sFieldName;
01192         }
01193 
01194         return $sCoreTableName . '__' . strtolower($sFieldName);
01195     }
01196 
01206     protected function _setFieldData($sFieldName, $sValue, $iDataType = oxField::T_TEXT)
01207     {
01208 
01209         $sLongFieldName = $this->_getFieldLongName($sFieldName);
01210         //$sLongFieldName = $this->_sCoreTable . "__" . strtolower($sFieldName);
01211 
01212         //T2008-03-14
01213         //doing this because in lazy loaded lists on first load it is harmful to have initialised fields but not yet set
01214         //situation: only first article is loaded fully for "select oxid from oxarticles"
01215         /*
01216         if ($this->_blUseLazyLoading && !isset($this->$sLongFieldName))
01217             return;*/
01218 
01219         //in non lazy loading case we just add a field and do not care about it more
01220         if (!$this->_blUseLazyLoading && !isset($this->$sLongFieldName)) {
01221             $aFields = $this->_getAllFields(true);
01222             if (isset($aFields[strtolower($sFieldName)])) {
01223                 $this->_addField($sFieldName, $this->_getFieldStatus($sFieldName));
01224             }
01225         }
01226         // if we have a double field we replace "," with "." in case somebody enters it in european format
01227         if (isset($this->$sLongFieldName) && isset($this->$sLongFieldName->fldtype) && $this->$sLongFieldName->fldtype == 'double') {
01228             $sValue = str_replace(',', '.', $sValue);
01229         }
01230 
01231         // isset is REQUIRED here not to use getter
01232         if (isset($this->$sLongFieldName) && is_object($this->$sLongFieldName)) {
01233             $this->$sLongFieldName->setValue($sValue, $iDataType);
01234         } else {
01235             $this->$sLongFieldName = new oxField($sValue, $iDataType);
01236         }
01237 
01238     }
01239 
01247     protected function _canFieldBeNull($sFieldName)
01248     {
01249         $aMetaData = $this->_getAllFields();
01250         foreach ($aMetaData as $oMetaInfo) {
01251             if (strcasecmp($oMetaInfo->name, $sFieldName) == 0) {
01252                 return !$oMetaInfo->not_null;
01253             }
01254         }
01255 
01256         return false;
01257     }
01258 
01266     protected function _getFieldDefaultValue($sFieldName)
01267     {
01268         $aMetaData = $this->_getAllFields();
01269         foreach ($aMetaData as $oMetaInfo) {
01270             if (strcasecmp($oMetaInfo->name, $sFieldName) == 0) {
01271                 return $oMetaInfo->default_value;
01272             }
01273         }
01274 
01275         return false;
01276     }
01277 
01286     protected function _getUpdateFieldValue($sFieldName, $oField)
01287     {
01288         $mValue = null;
01289         if ($oField instanceof oxField) {
01290             $mValue = $oField->getRawValue();
01291         } elseif (isset($oField->value)) {
01292             $mValue = $oField->value;
01293         }
01294 
01295         $oDb = oxDb::getDb();
01296         //Check if this field value is null AND it can be null according if not returning default value
01297         if ((null === $mValue)) {
01298             if ($this->_canFieldBeNull($sFieldName)) {
01299                 return 'null';
01300             } elseif ($mValue = $this->_getFieldDefaultValue($sFieldName)) {
01301                 return $oDb->quote($mValue);
01302             }
01303         }
01304 
01305         return $oDb->quote($mValue);
01306     }
01307 
01316     protected function _getUpdateFields($blUseSkipSaveFields = true)
01317     {
01318         $sSql = '';
01319         $blSep = false;
01320 
01321         foreach (array_keys($this->_aFieldNames) as $sKey) {
01322             $sLongName = $this->_getFieldLongName($sKey);
01323             $oField = $this->$sLongName;
01324 
01325 
01326             if (!$blUseSkipSaveFields || ($blUseSkipSaveFields && !in_array(strtolower($sKey), $this->_aSkipSaveFields))) {
01327                 $sSql .= (($blSep) ? ',' : '') . $sKey . ' = ' . $this->_getUpdateFieldValue($sKey, $oField);
01328                 $blSep = true;
01329             }
01330         }
01331 
01332         return $sSql;
01333     }
01334 
01344     protected function _update()
01345     {
01346         //do not allow derived item update
01347         if (!$this->allowDerivedUpdate()) {
01348             return false;
01349         }
01350 
01351 
01352         if (!$this->getId()) {
01356             $oEx = oxNew('oxObjectException');
01357             $oEx->setMessage('EXCEPTION_OBJECT_OXIDNOTSET');
01358             $oEx->setObject($this);
01359             throw $oEx;
01360         }
01361         $sCoreTableName = $this->getCoreTableName();
01362 
01363         $sIDKey = oxRegistry::getUtils()->getArrFldName($sCoreTableName . '.oxid');
01364         $this->$sIDKey = new oxField($this->getId(), oxField::T_RAW);
01365         $oDb = oxDb::getDb();
01366 
01367         $sUpdate = "update {$sCoreTableName} set " . $this->_getUpdateFields()
01368                    . " where {$sCoreTableName}.oxid = " . $oDb->quote($this->getId());
01369 
01370         //trigger event
01371         $this->beforeUpdate();
01372 
01373         $blRet = (bool) $oDb->execute($sUpdate);
01374 
01375         return $blRet;
01376     }
01377 
01385     protected function _insert()
01386     {
01387 
01388         $oDb = oxDb::getDb(oxDb::FETCH_MODE_ASSOC);
01389         $myConfig = $this->getConfig();
01390         $myUtils = oxRegistry::getUtils();
01391 
01392         // let's get a new ID
01393         if (!$this->getId()) {
01394             $this->setId();
01395         }
01396 
01397         $sIDKey = $myUtils->getArrFldName($this->getCoreTableName() . '.oxid');
01398         $this->$sIDKey = new oxField($this->getId(), oxField::T_RAW);
01399         $sInsert = "Insert into {$this->getCoreTableName()} set ";
01400 
01401         //setting oxshopid
01402         $sShopField = $myUtils->getArrFldName($this->getCoreTableName() . '.oxshopid');
01403 
01404         if (isset($this->$sShopField) && !$this->$sShopField->value) {
01405             $this->$sShopField = new oxField($myConfig->getShopId(), oxField::T_RAW);
01406         }
01407 
01408         $sInsert .= $this->_getUpdateFields($this->getUseSkipSaveFields());
01409 
01410         $blRet = (bool) $oDb->execute($sInsert);
01411 
01412 
01413         return $blRet;
01414     }
01415 
01416 
01423     protected function _isDisabledFieldCache()
01424     {
01425         $sClass = get_class($this);
01426         if (isset(self::$_blDisableFieldCaching[$sClass]) && self::$_blDisableFieldCaching[$sClass]) {
01427             return true;
01428         }
01429 
01430         return false;
01431     }
01432 
01436     protected function _addSkippedSaveFieldsForMapping()
01437     {
01438     }
01439 
01443     protected function _disableLazyLoadingForCaching()
01444     {
01445     }
01446 
01452     public function isOx()
01453     {
01454         $sOxId = $this->getId();
01455         if ($sOxId[0] == 'o' && $sOxId[1] == 'x') {
01456             return true;
01457         }
01458 
01459         return false;
01460     }
01461 
01467     public function isReadOnly()
01468     {
01469         return $this->_blReadOnly;
01470     }
01471 
01477     public function setReadOnly($blReadOnly)
01478     {
01479         $this->_blReadOnly = $blReadOnly;
01480     }
01481 
01487     public function getFieldNames()
01488     {
01489         return array_keys($this->_aFieldNames);
01490     }
01491 
01497     public function addFieldName($sName)
01498     {
01499         //preparation
01500         $sName = strtolower($sName);
01501         $this->_aFieldNames[$sName] = 0;
01502     }
01503 
01509     public function getLanguage()
01510     {
01511         return -1;
01512     }
01513 
01514 }