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 $_blReadOnly = false;
00136 
00142     protected $_blIsInList = false;
00143 
00149     protected $_isLoaded = false;
00150 
00156     protected $_aInnerLazyCache = null;
00157 
00163     protected $_blEmployMultilanguage = false;
00164 
00165 
00171     public function getUseSkipSaveFields()
00172     {
00173         return $this->_blUseSkipSaveFields;
00174     }
00175 
00181     public function setUseSkipSaveFields($blUseSkipSaveFields)
00182     {
00183         $this->_blUseSkipSaveFields = $blUseSkipSaveFields;
00184     }
00185 
00189     public function __construct()
00190     {
00191         // set active shop
00192         $myConfig = $this->getConfig();
00193         $this->_sCacheKey = $this->getViewName();
00194 
00195         $this->_addSkippedSaveFieldsForMapping();
00196         $this->_disableLazyLoadingForCaching();
00197 
00198         if ($this->_blUseLazyLoading) {
00199             $this->_sCacheKey .= $myConfig->getActiveView()->getClassName();
00200         } else {
00201             $this->_sCacheKey .= 'allviews';
00202         }
00203 
00204         //do not cache for admin?
00205         if ($this->isAdmin()) {
00206             $this->_sCacheKey = null;
00207         }
00208 
00209         $this->setShopId($myConfig->getShopId());
00210     }
00211 
00218     public function __set($sName, $sValue)
00219     {
00220         $this->$sName = $sValue;
00221         if ($this->_blUseLazyLoading && strpos($sName, $this->_sCoreTable . '__') === 0) {
00222             $sFieldName = str_replace($this->_sCoreTable . "__", '', $sName);
00223             if ($sFieldName != 'oxnid' && (!isset($this->_aFieldNames[$sFieldName]) || !$this->_aFieldNames[$sFieldName])) {
00224                 $aAllFields = $this->_getAllFields(true);
00225                 if (isset($aAllFields[strtolower($sFieldName)])) {
00226                     $iFieldStatus = $this->_getFieldStatus($sFieldName);
00227                     $this->_addField($sFieldName, $iFieldStatus);
00228                 }
00229             }
00230         }
00231     }
00232 
00240     public function __get($sName)
00241     {
00242         switch ($sName) {
00243             case 'blIsDerived':
00244                 return $this->isDerived();
00245                 break;
00246             case 'sOXID':
00247                 return $this->getId();
00248                 break;
00249             case 'blReadOnly':
00250                 return $this->isReadOnly();
00251                 break;
00252         }
00253 
00254         // implementing lazy loading fields
00255         // This part of the code is slow and normally is called before field cache is built.
00256         // Make sure it is not called after first page is loaded and cache data is fully built.
00257         if ($this->_blUseLazyLoading && stripos($sName, $this->_sCoreTable . "__") === 0) {
00258 
00259             if ($this->getId()) {
00260 
00261                 //lazy load it
00262                 $sFieldName = str_replace($this->_sCoreTable . '__', '', $sName);
00263                 $sCacheFieldName = strtoupper($sFieldName);
00264 
00265                 $iFieldStatus = $this->_getFieldStatus($sFieldName);
00266                 $sViewName = $this->getViewName();
00267                 $sId = $this->getId();
00268 
00269                 try {
00270                     if ($this->_aInnerLazyCache === null) {
00271 
00272                         $oDb = oxDb::getDb(oxDb::FETCH_MODE_ASSOC);
00273                         $sQ = 'SELECT * FROM ' . $sViewName . ' WHERE `oxid` = ' . $oDb->quote($sId);
00274                         $rs = $oDb->select($sQ);
00275                         if ($rs && $rs->RecordCount()) {
00276                             $this->_aInnerLazyCache = array_change_key_case($rs->fields, CASE_UPPER);
00277                             if (array_key_exists($sCacheFieldName, $this->_aInnerLazyCache)) {
00278                                 $sFieldValue = $this->_aInnerLazyCache[$sCacheFieldName];
00279                             } else {
00280                                 return null;
00281                             }
00282                         } else {
00283                             return null;
00284                         }
00285                     } elseif (array_key_exists($sCacheFieldName, $this->_aInnerLazyCache)) {
00286                         $sFieldValue = $this->_aInnerLazyCache[$sCacheFieldName];
00287                     } else {
00288                         return null;
00289                     }
00290 
00291                     $this->_addField($sFieldName, $iFieldStatus);
00292                     $this->_setFieldData($sFieldName, $sFieldValue);
00293 
00294                     //save names to cache for next loading
00295                     if ($this->_sCacheKey) {
00296                         $myUtils = oxRegistry::getUtils();
00297                         $sCacheKey = 'fieldnames_' . $this->_sCoreTable . '_' . $this->_sCacheKey;
00298                         $aFieldNames = $myUtils->fromFileCache($sCacheKey);
00299                         $aFieldNames[$sFieldName] = $iFieldStatus;
00300                         $myUtils->toFileCache($sCacheKey, $aFieldNames);
00301                     }
00302                 } catch (Exception $e) {
00303                     return null;
00304                 }
00305 
00306                 //do not use field cache for this page
00307                 //as if we use it for lists then objects are loaded empty instead of lazy loading.
00308                 self::$_blDisableFieldCaching[get_class($this)] = true;
00309             }
00310 
00311             oxUtilsObject::getInstance()->resetInstanceCache(get_class($this));
00312         }
00313 
00314         //returns stdClass implementing __toString() method due to uknown scenario where this var should be used.
00315         if (!isset($this->$sName)) {
00316             $this->$sName = null;
00317         }
00318 
00319         return $this->$sName;
00320     }
00321 
00329     public function __isset($mVar)
00330     {
00331         return isset($this->$mVar);
00332     }
00333 
00337     public function __clone()
00338     {
00339         if (!$this->_blIsSimplyClonable) {
00340             foreach ($this->_aFieldNames as $sField => $sVal) {
00341                 $sLongName = $this->_getFieldLongName($sField);
00342                 if (is_object($this->$sLongName)) {
00343                     $this->$sLongName = clone $this->$sLongName;
00344                 }
00345             }
00346         }
00347     }
00348 
00354     public function oxClone($oObject)
00355     {
00356         $aClasVars = get_object_vars($oObject);
00357         while (list($name, $value) = each($aClasVars)) {
00358             if (is_object($oObject->$name)) {
00359                 $this->$name = clone $oObject->$name;
00360             } else {
00361                 $this->$name = $oObject->$name;
00362             }
00363         }
00364     }
00365 
00372     public function init($sTableName = null, $blForceAllFields = false)
00373     {
00374         if ($sTableName) {
00375             $this->_sCoreTable = $sTableName;
00376         }
00377 
00378         // reset view table
00379         $this->_sViewTable = false;
00380 
00381         if (count($this->_aFieldNames) <= 1) {
00382             $this->_initDataStructure($blForceAllFields);
00383         }
00384     }
00385 
00393     public function assign($dbRecord)
00394     {
00395         if (!is_array($dbRecord)) {
00396             return;
00397         }
00398 
00399 
00400         reset($dbRecord);
00401         while (list($sName, $sValue) = each($dbRecord)) {
00402 
00403             // patch for IIS
00404             //TODO: test it on IIS do we still need it
00405             //if( is_array($value) && count( $value) == 1)
00406             //    $value = current( $value);
00407 
00408             $this->_setFieldData($sName, $sValue);
00409         }
00410 
00411         $sOxidField = $this->_getFieldLongName('oxid');
00412         $this->_sOXID = $this->$sOxidField->value;
00413 
00414     }
00415 
00421     public function getClassName()
00422     {
00423         return $this->_sClassName;
00424     }
00425 
00431     public function getCoreTableName()
00432     {
00433         return $this->_sCoreTable;
00434     }
00435 
00441     public function getId()
00442     {
00443         return $this->_sOXID;
00444     }
00445 
00453     public function setId($sOXID = null)
00454     {
00455         if ($sOXID) {
00456             $this->_sOXID = $sOXID;
00457         } else {
00458             if ($this->getCoreTableName() == 'oxobject2category') {
00459                 $sObjectId = $this->oxobject2category__oxobjectid;
00460                 $sCatId = $this->oxobject2category__oxcatnid;
00461                 $sShopID = $this->oxobject2category__oxshopid;
00462                 $this->_sOXID = md5($sObjectId . $sCatId . $sShopID);
00463             } else {
00464                 $this->_sOXID = oxUtilsObject::getInstance()->generateUID();
00465             }
00466         }
00467 
00468         $sIdVarName = $this->getCoreTableName() . '__oxid';
00469         $this->$sIdVarName = new oxField($this->_sOXID, oxField::T_RAW);
00470 
00471         return $this->_sOXID;
00472     }
00473 
00479     public function setShopId($iShopId)
00480     {
00481         $this->_iShopId = $iShopId;
00482     }
00483 
00489     public function getShopId()
00490     {
00491         return $this->_iShopId;
00492     }
00493 
00501     public function getViewName($blForceCoreTableUsage = null)
00502     {
00503         if (!$this->_sViewTable || ($blForceCoreTableUsage !== null)) {
00504             if ($blForceCoreTableUsage === true) {
00505                 return $this->getCoreTableName();
00506             }
00507 
00508 
00509             if (($blForceCoreTableUsage !== null) && $blForceCoreTableUsage) {
00510                 $iShopId = -1;
00511             } else {
00512                 $iShopId = oxRegistry::getConfig()->getShopId();
00513             }
00514 
00515             $sViewName = getViewName($this->getCoreTableName(), $this->_blEmployMultilanguage == false ? -1 : $this->getLanguage(), $iShopId);
00516             if ($blForceCoreTableUsage !== null) {
00517                 return $sViewName;
00518             }
00519             $this->_sViewTable = $sViewName;
00520         }
00521 
00522         return $this->_sViewTable;
00523     }
00524 
00531     public function modifyCacheKey($sCacheKey, $blOverride = false)
00532     {
00533         if ($blOverride) {
00534             $this->_sCacheKey = $sCacheKey;
00535         } else {
00536             $this->_sCacheKey .= $sCacheKey;
00537         }
00538     }
00539 
00543     public function disableLazyLoading()
00544     {
00545         $this->_blUseLazyLoading = false;
00546         $this->_initDataStructure(true);
00547     }
00548 
00549 
00555     public function isDerived()
00556     {
00557 
00558         return $this->_blIsDerived;
00559     }
00560 
00566     public function setIsDerived($blVal)
00567     {
00568         $this->_blIsDerived = $blVal;
00569     }
00570 
00577     public function isMultilang()
00578     {
00579         return false;
00580     }
00581 
00591     public function load($sOXID)
00592     {
00593 
00594         //getting at least one field before lazy loading the object
00595         $this->_addField('oxid', 0);
00596         $sSelect = $this->buildSelectString(array($this->getViewName() . '.oxid' => $sOXID));
00597         $this->_isLoaded = $this->assignRecord($sSelect);
00598 
00599 
00600         return $this->_isLoaded;
00601     }
00602 
00603 
00609     public function isLoaded()
00610     {
00611         return $this->_isLoaded;
00612     }
00613 
00621     public function buildSelectString($aWhere = null)
00622     {
00623         $oDB = oxDb::getDb();
00624 
00625         $sGet = $this->getSelectFields();
00626         $sSelect = "select $sGet from " . $this->getViewName() . ' where 1 ';
00627 
00628         if ($aWhere) {
00629             reset($aWhere);
00630             while (list($name, $value) = each($aWhere)) {
00631                 $sSelect .= ' and ' . $name . ' = ' . $oDB->quote($value);
00632             }
00633         }
00634 
00635         // add active shop
00636 
00637         return $sSelect;
00638     }
00639 
00647     public function assignRecord($sSelect)
00648     {
00649         $blRet = false;
00650 
00651         $rs = oxDb::getDb(oxDb::FETCH_MODE_ASSOC)->select($sSelect);
00652 
00653         if ($rs != false && $rs->recordCount() > 0) {
00654             $blRet = true;
00655             $this->assign($rs->fields);
00656         }
00657 
00658         return $blRet;
00659     }
00660 
00668     public function getFieldData($sFieldName)
00669     {
00670         $sLongFieldName = $this->_getFieldLongName($sFieldName);
00671 
00672         return $this->$sLongFieldName->value;
00673     }
00674 
00682     public function getSelectFields($blForceCoreTableUsage = null)
00683     {
00684         $aSelectFields = array();
00685 
00686         $sViewName = $this->getViewName($blForceCoreTableUsage);
00687 
00688         foreach ($this->_aFieldNames as $sKey => $sField) {
00689             if ($sViewName) {
00690                 $aSelectFields[] = "`$sViewName`.`$sKey`";
00691             } else {
00692                 $aSelectFields[] = ".`$sKey`";
00693             }
00694 
00695         }
00696 
00697         $sSelectFields = join(', ', $aSelectFields);
00698 
00699         return $sSelectFields;
00700     }
00701 
00709     public function delete($sOxId = null)
00710     {
00711         if (!$sOxId) {
00712             $sOxId = $this->getId();
00713 
00714             //do not allow derived deletion
00715             if (!$this->allowDerivedDelete()) {
00716                 return false;
00717             }
00718         }
00719 
00720         if (!$sOxId) {
00721             return false;
00722         }
00723 
00724 
00725         $this->_removeElement2ShopRelations($sOxId);
00726 
00727         $oDB = oxDb::getDb(oxDb::FETCH_MODE_ASSOC);
00728         $sCoreTable = $this->getCoreTableName();
00729         $sDelete = "delete from {$sCoreTable} where oxid = " . $oDB->quote($sOxId);
00730         $oDB->execute($sDelete);
00731         if ($blDelete = (bool) $oDB->affected_Rows()) {
00732             $this->onChange(ACTION_DELETE, $sOxId);
00733         }
00734 
00735         return $blDelete;
00736     }
00737 
00743     protected function _removeElement2ShopRelations($sOxId)
00744     {
00745     }
00746 
00747 
00753     public function save()
00754     {
00755         if (!is_array($this->_aFieldNames)) {
00756             return false;
00757         }
00758 
00759         // #739A - should be executed here because of date/time formatting feature
00760         if ($this->isAdmin() && !$this->getConfig()->getConfigParam('blSkipFormatConversion')) {
00761             foreach ($this->_aFieldNames as $sName => $sVal) {
00762                 $sLongName = $this->_getFieldLongName($sName);
00763                 if (isset($this->$sLongName->fldtype) && $this->$sLongName->fldtype == 'datetime') {
00764                     oxRegistry::get('oxUtilsDate')->convertDBDateTime($this->$sLongName, true);
00765                 } elseif (isset($this->$sLongName->fldtype) && $this->$sLongName->fldtype == 'timestamp') {
00766                     oxRegistry::get('oxUtilsDate')->convertDBTimestamp($this->$sLongName, true);
00767                 } elseif (isset($this->$sLongName->fldtype) && $this->$sLongName->fldtype == 'date') {
00768                     oxRegistry::get('oxUtilsDate')->convertDBDate($this->$sLongName, true);
00769                 }
00770             }
00771         }
00772 
00773         if ($this->exists()) {
00774             //do not allow derived update
00775             if (!$this->allowDerivedUpdate()) {
00776                 return false;
00777             }
00778 
00779             $blRet = $this->_update();
00780             $sAction = ACTION_UPDATE;
00781         } else {
00782             $blRet = $this->_insert();
00783             $sAction = ACTION_INSERT;
00784         }
00785 
00786         $this->onChange($sAction);
00787 
00788         if ($blRet) {
00789             return $this->getId();
00790         } else {
00791             return false;
00792         }
00793     }
00794 
00800     public function allowDerivedUpdate()
00801     {
00802         return !$this->isDerived();
00803     }
00804 
00810     public function allowDerivedDelete()
00811     {
00812         return !$this->isDerived();
00813     }
00814 
00822     public function exists($sOXID = null)
00823     {
00824         if (!$sOXID) {
00825             $sOXID = $this->getId();
00826         }
00827         if (!$sOXID) {
00828             return false;
00829         }
00830 
00831         $sViewName = $this->getCoreTableName();
00832         $oDb = oxDb::getDb(oxDb::FETCH_MODE_ASSOC);
00833         $sSelect = "select {$this->_sExistKey} from {$sViewName} where {$this->_sExistKey} = " . $oDb->quote($sOXID);
00834 
00835         return ( bool ) $oDb->getOne($sSelect, false, false);
00836     }
00837 
00845     public function getSqlActiveSnippet($blForceCoreTable = null)
00846     {
00847         $sQ = '';
00848         $sTable = $this->getViewName($blForceCoreTable);
00849 
00850         // has 'active' field ?
00851         if (isset($this->_aFieldNames['oxactive'])) {
00852             $sQ = " $sTable.oxactive = 1 ";
00853         }
00854 
00855         // has 'activefrom'/'activeto' fields ?
00856         if (isset($this->_aFieldNames['oxactivefrom']) && isset($this->_aFieldNames['oxactiveto'])) {
00857 
00858             $sDate = date('Y-m-d H:i:s', oxRegistry::get('oxUtilsDate')->getTime());
00859 
00860             $sQ = $sQ ? " $sQ or " : '';
00861             $sQ = " ( $sQ ( $sTable.oxactivefrom < '$sDate' and $sTable.oxactiveto > '$sDate' ) ) ";
00862         }
00863 
00864         return $sQ;
00865     }
00866 
00873     public function beforeUpdate($sOXID = null)
00874     {
00875     }
00876 
00885     public function onChange($iAction = null, $sOXID = null)
00886     {
00887     }
00888 
00889 
00893     public function setInList()
00894     {
00895         $this->_blIsInList = true;
00896     }
00897 
00903     protected function _isInList()
00904     {
00905         return $this->_blIsInList;
00906     }
00907 
00916     protected function _getObjectViewName($sTable, $sShopID = null)
00917     {
00918 
00919         return getViewName($sTable, -1, $sShopID);
00920     }
00921 
00922 
00933     protected function _getTableFields($sTable, $blReturnSimple = false)
00934     {
00935         $myUtils = oxRegistry::getUtils();
00936 
00937         $sCacheKey = $sTable . '_allfields_' . $blReturnSimple;
00938         $aMetaFields = $myUtils->fromFileCache($sCacheKey);
00939 
00940         if ($aMetaFields) {
00941             return $aMetaFields;
00942         }
00943 
00944         $aMetaFields = oxDb::getInstance()->getTableDescription($sTable);
00945 
00946         if (!$blReturnSimple) {
00947             $myUtils->toFileCache($sCacheKey, $aMetaFields);
00948 
00949             return $aMetaFields;
00950         }
00951 
00952         //returning simple array
00953         $aRet = array();
00954         if (is_array($aMetaFields)) {
00955             foreach ($aMetaFields as $oVal) {
00956                 $aRet[strtolower($oVal->name)] = 0;
00957             }
00958         }
00959 
00960         $myUtils->toFileCache($sCacheKey, $aRet);
00961 
00962         return $aRet;
00963     }
00964 
00976     protected function _getAllFields($blReturnSimple = false)
00977     {
00978         if (!$this->getCoreTableName()) {
00979             return array();
00980         }
00981 
00982         return $this->_getTableFields($this->getCoreTableName(), $blReturnSimple);
00983     }
00984 
00991     protected function _initDataStructure($blForceFullStructure = false)
00992     {
00993         $myUtils = oxRegistry::getUtils();
00994 
00995         //get field names from cache
00996         $aFieldNames = null;
00997         $sFullCacheKey = 'fieldnames_' . $this->getCoreTableName() . '_' . $this->_sCacheKey;
00998         if ($this->_sCacheKey && !$this->_isDisabledFieldCache()) {
00999             $aFieldNames = $myUtils->fromFileCache($sFullCacheKey);
01000         }
01001 
01002         if (!$aFieldNames) {
01003             $aFieldNames = $this->_getNonCachedFieldNames($blForceFullStructure);
01004             if ($this->_sCacheKey && !$this->_isDisabledFieldCache()) {
01005                 $myUtils->toFileCache($sFullCacheKey, $aFieldNames);
01006             }
01007         }
01008 
01009         if ($aFieldNames !== false) {
01010             foreach ($aFieldNames as $sField => $sStatus) {
01011                 $this->_addField($sField, $sStatus);
01012             }
01013         }
01014     }
01015 
01027     protected function _getNonCachedFieldNames($blForceFullStructure = false)
01028     {
01029         //T2008-02-22
01030         //so if this method is executed on cached version we see it when profiling
01031         startProfile('!__CACHABLE__!');
01032 
01033         //case 1. (admin)
01034         if ($this->isAdmin()) {
01035             $aMetaFields = $this->_getAllFields();
01036             foreach ($aMetaFields as $oField) {
01037                 if ($oField->max_length == -1) {
01038                     $oField->max_length = 10; // double or float
01039                 }
01040 
01041                 if ($oField->type == 'datetime') {
01042                     $oField->max_length = 20;
01043                 }
01044 
01045                 $this->_addField($oField->name, $this->_getFieldStatus($oField->name), $oField->type, $oField->max_length);
01046             }
01047             stopProfile('!__CACHABLE__!');
01048 
01049             return false;
01050         }
01051 
01052         //case 2. (just get all fields)
01053         if ($blForceFullStructure || !$this->_blUseLazyLoading) {
01054             $aMetaFields = $this->_getAllFields(true);
01055             /*
01056             foreach ( $aMetaFields as $sFieldName => $sVal) {
01057                 $this->_addField( $sFieldName, $this->_getFieldStatus($sFieldName));
01058             }*/
01059             stopProfile('!__CACHABLE__!');
01060 
01061             return $aMetaFields;
01062         }
01063 
01064         //case 3. (get only oxid field, so we can fetch the rest of the fields over lazy loading mechanism)
01065         stopProfile('!__CACHABLE__!');
01066 
01067         return array('oxid' => 0);
01068     }
01069 
01078     protected function _getFieldStatus($sFieldName)
01079     {
01080         return 0;
01081     }
01082 
01093     protected function _addField($sName, $iStatus, $sType = null, $sLength = null)
01094     {
01095         //preparation
01096         $sName = strtolower($sName);
01097 
01098         //adding field names element
01099         $this->_aFieldNames[$sName] = $iStatus;
01100 
01101         //already set?
01102         $sLongName = $this->_getFieldLongName($sName);
01103         if (isset($this->$sLongName)) {
01104             return;
01105         }
01106 
01107         //defining the field
01108         $oField = false;
01109 
01110         if (isset($sType)) {
01111             $oField = new oxField();
01112             $oField->fldtype = $sType;
01113             //T2008-01-29
01114             //can't clone as the fields are objects and are not fully cloned
01115             $this->_blIsSimplyClonable = false;
01116         }
01117 
01118         if (isset($sLength)) {
01119             if (!$oField) {
01120                 $oField = new oxField();
01121             }
01122             $oField->fldmax_length = $sLength;
01123             $this->_blIsSimplyClonable = false;
01124         }
01125 
01126         $this->$sLongName = $oField;
01127     }
01128 
01136     protected function _getFieldLongName($sFieldName)
01137     {
01138         //trying to avoid strpos call as often as possible
01139         $sCoreTableName = $this->getCoreTableName();
01140         if ($sFieldName[2] == $sCoreTableName[2] && strpos($sFieldName, $sCoreTableName . '__') === 0) {
01141             return $sFieldName;
01142         }
01143 
01144         return $sCoreTableName . '__' . strtolower($sFieldName);
01145     }
01146 
01156     protected function _setFieldData($sFieldName, $sValue, $iDataType = oxField::T_TEXT)
01157     {
01158 
01159         $sLongFieldName = $this->_getFieldLongName($sFieldName);
01160         //$sLongFieldName = $this->_sCoreTable . "__" . strtolower($sFieldName);
01161 
01162         //T2008-03-14
01163         //doing this because in lazy loaded lists on first load it is harmful to have initialised fields but not yet set
01164         //situation: only first article is loaded fully for "select oxid from oxarticles"
01165         /*
01166         if ($this->_blUseLazyLoading && !isset($this->$sLongFieldName))
01167             return;*/
01168 
01169         //in non lazy loading case we just add a field and do not care about it more
01170         if (!$this->_blUseLazyLoading && !isset($this->$sLongFieldName)) {
01171             $aFields = $this->_getAllFields(true);
01172             if (isset($aFields[strtolower($sFieldName)])) {
01173                 $this->_addField($sFieldName, $this->_getFieldStatus($sFieldName));
01174             }
01175         }
01176         // if we have a double field we replace "," with "." in case somebody enters it in european format
01177         if (isset($this->$sLongFieldName) && isset($this->$sLongFieldName->fldtype) && $this->$sLongFieldName->fldtype == 'double') {
01178             $sValue = str_replace(',', '.', $sValue);
01179         }
01180 
01181         // isset is REQUIRED here not to use getter
01182         if (isset($this->$sLongFieldName) && is_object($this->$sLongFieldName)) {
01183             $this->$sLongFieldName->setValue($sValue, $iDataType);
01184         } else {
01185             $this->$sLongFieldName = new oxField($sValue, $iDataType);
01186         }
01187 
01188     }
01189 
01197     protected function _canFieldBeNull($sFieldName)
01198     {
01199         $aMetaData = $this->_getAllFields();
01200         foreach ($aMetaData as $oMetaInfo) {
01201             if (strcasecmp($oMetaInfo->name, $sFieldName) == 0) {
01202                 return !$oMetaInfo->not_null;
01203             }
01204         }
01205 
01206         return false;
01207     }
01208 
01216     protected function _getFieldDefaultValue($sFieldName)
01217     {
01218         $aMetaData = $this->_getAllFields();
01219         foreach ($aMetaData as $oMetaInfo) {
01220             if (strcasecmp($oMetaInfo->name, $sFieldName) == 0) {
01221                 return $oMetaInfo->default_value;
01222             }
01223         }
01224 
01225         return false;
01226     }
01227 
01236     protected function _getUpdateFieldValue($sFieldName, $oField)
01237     {
01238         $mValue = null;
01239         if ($oField instanceof oxField) {
01240             $mValue = $oField->getRawValue();
01241         } elseif (isset($oField->value)) {
01242             $mValue = $oField->value;
01243         }
01244 
01245         $oDb = oxDb::getDb();
01246         //Check if this field value is null AND it can be null according if not returning default value
01247         if ((null === $mValue)) {
01248             if ($this->_canFieldBeNull($sFieldName)) {
01249                 return 'null';
01250             } elseif ($mValue = $this->_getFieldDefaultValue($sFieldName)) {
01251                 return $oDb->quote($mValue);
01252             }
01253         }
01254 
01255         return $oDb->quote($mValue);
01256     }
01257 
01266     protected function _getUpdateFields($blUseSkipSaveFields = true)
01267     {
01268         $sSql = '';
01269         $blSep = false;
01270 
01271         foreach (array_keys($this->_aFieldNames) as $sKey) {
01272             $sLongName = $this->_getFieldLongName($sKey);
01273             $oField = $this->$sLongName;
01274 
01275 
01276             if (!$blUseSkipSaveFields || ($blUseSkipSaveFields && !in_array(strtolower($sKey), $this->_aSkipSaveFields))) {
01277                 $sSql .= (($blSep) ? ',' : '') . $sKey . ' = ' . $this->_getUpdateFieldValue($sKey, $oField);
01278                 $blSep = true;
01279             }
01280         }
01281 
01282         return $sSql;
01283     }
01284 
01294     protected function _update()
01295     {
01296         //do not allow derived item update
01297         if (!$this->allowDerivedUpdate()) {
01298             return false;
01299         }
01300 
01301 
01302         if (!$this->getId()) {
01306             $oEx = oxNew('oxObjectException');
01307             $oEx->setMessage('EXCEPTION_OBJECT_OXIDNOTSET');
01308             $oEx->setObject($this);
01309             throw $oEx;
01310         }
01311         $sCoreTableName = $this->getCoreTableName();
01312 
01313         $sIDKey = oxRegistry::getUtils()->getArrFldName($sCoreTableName . '.oxid');
01314         $this->$sIDKey = new oxField($this->getId(), oxField::T_RAW);
01315         $oDb = oxDb::getDb();
01316 
01317         $sUpdate = "update {$sCoreTableName} set " . $this->_getUpdateFields()
01318                    . " where {$sCoreTableName}.oxid = " . $oDb->quote($this->getId());
01319 
01320         //trigger event
01321         $this->beforeUpdate();
01322 
01323         $blRet = (bool) $oDb->execute($sUpdate);
01324 
01325         return $blRet;
01326     }
01327 
01335     protected function _insert()
01336     {
01337 
01338         $oDb = oxDb::getDb(oxDb::FETCH_MODE_ASSOC);
01339         $myConfig = $this->getConfig();
01340         $myUtils = oxRegistry::getUtils();
01341 
01342         // let's get a new ID
01343         if (!$this->getId()) {
01344             $this->setId();
01345         }
01346 
01347         $sIDKey = $myUtils->getArrFldName($this->getCoreTableName() . '.oxid');
01348         $this->$sIDKey = new oxField($this->getId(), oxField::T_RAW);
01349         $sInsert = "Insert into {$this->getCoreTableName()} set ";
01350 
01351         //setting oxshopid
01352         $sShopField = $myUtils->getArrFldName($this->getCoreTableName() . '.oxshopid');
01353 
01354         if (isset($this->$sShopField) && !$this->$sShopField->value) {
01355             $this->$sShopField = new oxField($myConfig->getShopId(), oxField::T_RAW);
01356         }
01357 
01358         $sInsert .= $this->_getUpdateFields($this->getUseSkipSaveFields());
01359 
01360         $blRet = (bool) $oDb->execute($sInsert);
01361 
01362 
01363         return $blRet;
01364     }
01365 
01366 
01373     protected function _isDisabledFieldCache()
01374     {
01375         $sClass = get_class($this);
01376         if (isset(self::$_blDisableFieldCaching[$sClass]) && self::$_blDisableFieldCaching[$sClass]) {
01377             return true;
01378         }
01379 
01380         return false;
01381     }
01382 
01386     protected function _addSkippedSaveFieldsForMapping()
01387     {
01388     }
01389 
01393     protected function _disableLazyLoadingForCaching()
01394     {
01395     }
01396 
01402     public function isOx()
01403     {
01404         $sOxId = $this->getId();
01405         if ($sOxId[0] == 'o' && $sOxId[1] == 'x') {
01406             return true;
01407         }
01408 
01409         return false;
01410     }
01411 
01417     public function isReadOnly()
01418     {
01419         return $this->_blReadOnly;
01420     }
01421 
01427     public function setReadOnly($blReadOnly)
01428     {
01429         $this->_blReadOnly = $blReadOnly;
01430     }
01431 
01437     public function getFieldNames()
01438     {
01439         return array_keys($this->_aFieldNames);
01440     }
01441 
01447     public function addFieldName($sName)
01448     {
01449         //preparation
01450         $sName = strtolower($sName);
01451         $this->_aFieldNames[$sName] = 0;
01452     }
01453 
01459     public function getLanguage()
01460     {
01461         return -1;
01462     }
01463 
01464 }