OXID eShop CE  4.10.1
 All Classes Namespaces Files Functions Variables Pages
oxbase.php
Go to the documentation of this file.
1 <?php
2 
6 DEFINE('ACTION_NA', 0);
7 DEFINE('ACTION_DELETE', 1);
8 DEFINE('ACTION_INSERT', 2);
9 DEFINE('ACTION_UPDATE', 3);
10 DEFINE('ACTION_UPDATE_STOCK', 4);
11 
16 class oxBase extends oxSuperCfg
17 {
18 
24  protected $_sOXID = null;
25 
31  protected $_iShopId = null;
32 
38  protected $_blIsSimplyClonable = true;
39 
45  protected $_sClassName = 'oxbase';
46 
52  protected $_sCoreTable = null;
53 
59  protected $_sViewTable = null;
60 
61 
67  protected $_aFieldNames = array('oxid' => 0);
68 
74  protected $_sCacheKey = null;
75 
81  protected $_blUseLazyLoading = false;
82 
88  protected $_aSkipSaveFields = array('oxtimestamp');
89 
95  protected $_blUseSkipSaveFields = true;
96 
102  protected $_sExistKey = 'oxid';
103 
110  protected $_blIsDerived = null;
111 
121  protected static $_blDisableFieldCaching = array();
122 
128  protected $_blIsSeoObject = false;
129 
135  protected $_blUpdateSeo = true;
136 
142  protected $_blReadOnly = false;
143 
149  protected $_blIsInList = false;
150 
156  protected $_isLoaded = false;
157 
163  protected $_aInnerLazyCache = null;
164 
170  protected $_blEmployMultilanguage = false;
171 
172 
178  public function getUseSkipSaveFields()
179  {
181  }
182 
188  public function setUseSkipSaveFields($blUseSkipSaveFields)
189  {
190  $this->_blUseSkipSaveFields = $blUseSkipSaveFields;
191  }
192 
196  public function __construct()
197  {
198  // set active shop
199  $myConfig = $this->getConfig();
200  $this->_sCacheKey = $this->getViewName();
201 
204 
205  if ($this->_blUseLazyLoading) {
206  $this->_sCacheKey .= $myConfig->getActiveView()->getClassName();
207  } else {
208  $this->_sCacheKey .= 'allviews';
209  }
210 
211  //do not cache for admin?
212  if ($this->isAdmin()) {
213  $this->_sCacheKey = null;
214  }
215 
216  $this->setShopId($myConfig->getShopId());
217  }
218 
225  public function __set($sName, $sValue)
226  {
227  $this->$sName = $sValue;
228  if ($this->_blUseLazyLoading && strpos($sName, $this->_sCoreTable . '__') === 0) {
229  $sFieldName = str_replace($this->_sCoreTable . "__", '', $sName);
230  if ($sFieldName != 'oxnid' && (!isset($this->_aFieldNames[$sFieldName]) || !$this->_aFieldNames[$sFieldName])) {
231  $aAllFields = $this->_getAllFields(true);
232  if (isset($aAllFields[strtolower($sFieldName)])) {
233  $iFieldStatus = $this->_getFieldStatus($sFieldName);
234  $this->_addField($sFieldName, $iFieldStatus);
235  }
236  }
237  }
238  }
239 
247  public function __get($sName)
248  {
249  switch ($sName) {
250  case 'blIsDerived':
251  return $this->isDerived();
252  break;
253  case 'sOXID':
254  return $this->getId();
255  break;
256  case 'blReadOnly':
257  return $this->isReadOnly();
258  break;
259  }
260 
261  // implementing lazy loading fields
262  // This part of the code is slow and normally is called before field cache is built.
263  // Make sure it is not called after first page is loaded and cache data is fully built.
264  if ($this->_blUseLazyLoading && stripos($sName, $this->_sCoreTable . "__") === 0) {
265 
266  if ($this->getId()) {
267 
268  //lazy load it
269  $sFieldName = str_replace($this->_sCoreTable . '__', '', $sName);
270  $sCacheFieldName = strtoupper($sFieldName);
271 
272  $iFieldStatus = $this->_getFieldStatus($sFieldName);
273  $sViewName = $this->getViewName();
274  $sId = $this->getId();
275 
276  try {
277  if ($this->_aInnerLazyCache === null) {
278 
280  $sQ = 'SELECT * FROM ' . $sViewName . ' WHERE `oxid` = ' . $oDb->quote($sId);
281  $rs = $oDb->select($sQ);
282  if ($rs && $rs->RecordCount()) {
283  $this->_aInnerLazyCache = array_change_key_case($rs->fields, CASE_UPPER);
284  if (array_key_exists($sCacheFieldName, $this->_aInnerLazyCache)) {
285  $sFieldValue = $this->_aInnerLazyCache[$sCacheFieldName];
286  } else {
287  return null;
288  }
289  } else {
290  return null;
291  }
292  } elseif (array_key_exists($sCacheFieldName, $this->_aInnerLazyCache)) {
293  $sFieldValue = $this->_aInnerLazyCache[$sCacheFieldName];
294  } else {
295  return null;
296  }
297 
298  $this->_addField($sFieldName, $iFieldStatus);
299  $this->_setFieldData($sFieldName, $sFieldValue);
300 
301  //save names to cache for next loading
302  if ($this->_sCacheKey) {
303  $myUtils = oxRegistry::getUtils();
304  $sCacheKey = 'fieldnames_' . $this->_sCoreTable . '_' . $this->_sCacheKey;
305  $aFieldNames = $myUtils->fromFileCache($sCacheKey);
306  $aFieldNames[$sFieldName] = $iFieldStatus;
307  $myUtils->toFileCache($sCacheKey, $aFieldNames);
308  }
309  } catch (Exception $e) {
310  return null;
311  }
312 
313  //do not use field cache for this page
314  //as if we use it for lists then objects are loaded empty instead of lazy loading.
315  self::$_blDisableFieldCaching[get_class($this)] = true;
316  }
317 
318  oxUtilsObject::getInstance()->resetInstanceCache(get_class($this));
319  }
320 
321  //returns stdClass implementing __toString() method due to uknown scenario where this var should be used.
322  if (!isset($this->$sName)) {
323  $this->$sName = null;
324  }
325 
326  return $this->$sName;
327  }
328 
336  public function __isset($mVar)
337  {
338  return isset($this->$mVar);
339  }
340 
344  public function __clone()
345  {
346  if (!$this->_blIsSimplyClonable) {
347  foreach ($this->_aFieldNames as $sField => $sVal) {
348  $sLongName = $this->_getFieldLongName($sField);
349  if (is_object($this->$sLongName)) {
350  $this->$sLongName = clone $this->$sLongName;
351  }
352  }
353  }
354  }
355 
361  public function oxClone($oObject)
362  {
363  $aClasVars = get_object_vars($oObject);
364  while (list($name, $value) = each($aClasVars)) {
365  if (is_object($oObject->$name)) {
366  $this->$name = clone $oObject->$name;
367  } else {
368  $this->$name = $oObject->$name;
369  }
370  }
371  }
372 
378  public function getUpdateSeo()
379  {
380  return $this->_blUpdateSeo;
381  }
382 
388  public function setUpdateSeo($blUpdateSeo)
389  {
390  $this->_blUpdateSeo = $blUpdateSeo;
391  }
392 
400  protected function _setUpdateSeoOnFieldChange($sField)
401  {
402  if ($this->getId() && in_array($sField, $this->getFieldNames())) {
403  $oDb = oxDb::getDb();
404  $sTableName = $this->getCoreTableName();
405  $sQuotedOxid = $oDb->quote($this->getId());
406  $sTitle = $oDb->getOne("select `{$sField}` from `{$sTableName}` where `oxid` = {$sQuotedOxid}");
407  $sFieldValue = "{$sTableName}__{$sField}";
408  $sCurrentTitle = $this->$sFieldValue->value;
409 
410  if ($sTitle == $sCurrentTitle) {
411  $this->setUpdateSeo(false);
412  }
413  }
414  }
415 
422  public function init($sTableName = null, $blForceAllFields = false)
423  {
424  if ($sTableName) {
425  $this->_sCoreTable = $sTableName;
426  }
427 
428  // reset view table
429  $this->_sViewTable = false;
430 
431  if (count($this->_aFieldNames) <= 1) {
432  $this->_initDataStructure($blForceAllFields);
433  }
434  }
435 
443  public function assign($dbRecord)
444  {
445  if (!is_array($dbRecord)) {
446  return;
447  }
448 
449 
450  reset($dbRecord);
451  while (list($sName, $sValue) = each($dbRecord)) {
452 
453  // patch for IIS
454  //TODO: test it on IIS do we still need it
455  //if( is_array($value) && count( $value) == 1)
456  // $value = current( $value);
457 
458  $this->_setFieldData($sName, $sValue);
459  }
460 
461  $sOxidField = $this->_getFieldLongName('oxid');
462  $this->_sOXID = $this->$sOxidField->value;
463 
464  }
465 
471  public function getClassName()
472  {
473  return $this->_sClassName;
474  }
475 
481  public function getCoreTableName()
482  {
483  return $this->_sCoreTable;
484  }
485 
491  public function getId()
492  {
493  return $this->_sOXID;
494  }
495 
503  public function setId($sOXID = null)
504  {
505  if ($sOXID) {
506  $this->_sOXID = $sOXID;
507  } else {
508  if ($this->getCoreTableName() == 'oxobject2category') {
509  $sObjectId = $this->oxobject2category__oxobjectid;
510  $sCatId = $this->oxobject2category__oxcatnid;
511  $sShopID = $this->oxobject2category__oxshopid;
512  $this->_sOXID = md5($sObjectId . $sCatId . $sShopID);
513  } else {
514  $this->_sOXID = oxUtilsObject::getInstance()->generateUID();
515  }
516  }
517 
518  $sIdVarName = $this->getCoreTableName() . '__oxid';
519  $this->$sIdVarName = new oxField($this->_sOXID, oxField::T_RAW);
520 
521  return $this->_sOXID;
522  }
523 
529  public function setShopId($iShopId)
530  {
531  $this->_iShopId = $iShopId;
532  }
533 
539  public function getShopId()
540  {
541  return $this->_iShopId;
542  }
543 
551  public function getViewName($blForceCoreTableUsage = null)
552  {
553  if (!$this->_sViewTable || ($blForceCoreTableUsage !== null)) {
554  if ($blForceCoreTableUsage === true) {
555  return $this->getCoreTableName();
556  }
557 
558 
559  if (($blForceCoreTableUsage !== null) && $blForceCoreTableUsage) {
560  $iShopId = -1;
561  } else {
562  $iShopId = oxRegistry::getConfig()->getShopId();
563  }
564 
565  $sViewName = getViewName($this->getCoreTableName(), $this->_blEmployMultilanguage == false ? -1 : $this->getLanguage(), $iShopId);
566  if ($blForceCoreTableUsage !== null) {
567  return $sViewName;
568  }
569  $this->_sViewTable = $sViewName;
570  }
571 
572  return $this->_sViewTable;
573  }
574 
581  public function modifyCacheKey($sCacheKey, $blOverride = false)
582  {
583  if ($blOverride) {
584  $this->_sCacheKey = $sCacheKey;
585  } else {
586  $this->_sCacheKey .= $sCacheKey;
587  }
588  }
589 
593  public function disableLazyLoading()
594  {
595  $this->_blUseLazyLoading = false;
596  $this->_initDataStructure(true);
597  }
598 
599 
605  public function isDerived()
606  {
607 
608  return $this->_blIsDerived;
609  }
610 
616  public function setIsDerived($blVal)
617  {
618  $this->_blIsDerived = $blVal;
619  }
620 
627  public function isMultilang()
628  {
629  return false;
630  }
631 
641  public function load($sOXID)
642  {
643 
644  //getting at least one field before lazy loading the object
645  $this->_addField('oxid', 0);
646  $sSelect = $this->buildSelectString(array($this->getViewName() . '.oxid' => $sOXID));
647  $this->_isLoaded = $this->assignRecord($sSelect);
648 
649 
650  return $this->_isLoaded;
651  }
652 
653 
659  public function isLoaded()
660  {
661  return $this->_isLoaded;
662  }
663 
671  public function buildSelectString($aWhere = null)
672  {
673  $oDB = oxDb::getDb();
674 
675  $sGet = $this->getSelectFields();
676  $sSelect = "select $sGet from " . $this->getViewName() . ' where 1 ';
677 
678  if ($aWhere) {
679  reset($aWhere);
680  while (list($name, $value) = each($aWhere)) {
681  $sSelect .= ' and ' . $name . ' = ' . $oDB->quote($value);
682  }
683  }
684 
685  // add active shop
686 
687  return $sSelect;
688  }
689 
697  public function assignRecord($sSelect)
698  {
699  $blRet = false;
700 
701  $rs = oxDb::getDb(oxDb::FETCH_MODE_ASSOC)->select($sSelect);
702 
703  if ($rs != false && $rs->recordCount() > 0) {
704  $blRet = true;
705  $this->assign($rs->fields);
706  }
707 
708  return $blRet;
709  }
710 
718  public function getFieldData($sFieldName)
719  {
720  $sLongFieldName = $this->_getFieldLongName($sFieldName);
721 
722  return $this->$sLongFieldName->value;
723  }
724 
732  public function getSelectFields($blForceCoreTableUsage = null)
733  {
734  $aSelectFields = array();
735 
736  $sViewName = $this->getViewName($blForceCoreTableUsage);
737 
738  foreach ($this->_aFieldNames as $sKey => $sField) {
739  if ($sViewName) {
740  $aSelectFields[] = "`$sViewName`.`$sKey`";
741  } else {
742  $aSelectFields[] = ".`$sKey`";
743  }
744 
745  }
746 
747  $sSelectFields = join(', ', $aSelectFields);
748 
749  return $sSelectFields;
750  }
751 
759  public function delete($sOxId = null)
760  {
761  if (!$sOxId) {
762  $sOxId = $this->getId();
763 
764  //do not allow derived deletion
765  if (!$this->allowDerivedDelete()) {
766  return false;
767  }
768  }
769 
770  if (!$sOxId) {
771  return false;
772  }
773 
774 
775  $this->_removeElement2ShopRelations($sOxId);
776 
778  $sCoreTable = $this->getCoreTableName();
779  $sDelete = "delete from {$sCoreTable} where oxid = " . $oDB->quote($sOxId);
780  $oDB->execute($sDelete);
781  if ($blDelete = (bool) $oDB->affected_Rows()) {
782  $this->onChange(ACTION_DELETE, $sOxId);
783  }
784 
785  return $blDelete;
786  }
787 
793  protected function _removeElement2ShopRelations($sOxId)
794  {
795  }
796 
797 
803  public function save()
804  {
805  if (!is_array($this->_aFieldNames)) {
806  return false;
807  }
808 
809  // #739A - should be executed here because of date/time formatting feature
810  if ($this->isAdmin() && !$this->getConfig()->getConfigParam('blSkipFormatConversion')) {
811  foreach ($this->_aFieldNames as $sName => $sVal) {
812  $sLongName = $this->_getFieldLongName($sName);
813  if (isset($this->$sLongName->fldtype) && $this->$sLongName->fldtype == 'datetime') {
814  oxRegistry::get('oxUtilsDate')->convertDBDateTime($this->$sLongName, true);
815  } elseif (isset($this->$sLongName->fldtype) && $this->$sLongName->fldtype == 'timestamp') {
816  oxRegistry::get('oxUtilsDate')->convertDBTimestamp($this->$sLongName, true);
817  } elseif (isset($this->$sLongName->fldtype) && $this->$sLongName->fldtype == 'date') {
818  oxRegistry::get('oxUtilsDate')->convertDBDate($this->$sLongName, true);
819  }
820  }
821  }
822 
823  if ($this->exists()) {
824  //do not allow derived update
825  if (!$this->allowDerivedUpdate()) {
826  return false;
827  }
828 
829  $blRet = $this->_update();
830  $sAction = ACTION_UPDATE;
831  } else {
832  $blRet = $this->_insert();
833  $sAction = ACTION_INSERT;
834  }
835 
836  $this->onChange($sAction);
837 
838  if ($blRet) {
839  return $this->getId();
840  } else {
841  return false;
842  }
843  }
844 
850  public function allowDerivedUpdate()
851  {
852  return !$this->isDerived();
853  }
854 
860  public function allowDerivedDelete()
861  {
862  return !$this->isDerived();
863  }
864 
872  public function exists($sOXID = null)
873  {
874  if (!$sOXID) {
875  $sOXID = $this->getId();
876  }
877  if (!$sOXID) {
878  return false;
879  }
880 
881  $sViewName = $this->getCoreTableName();
883  $sSelect = "select {$this->_sExistKey} from {$sViewName} where {$this->_sExistKey} = " . $oDb->quote($sOXID);
884 
885  return ( bool ) $oDb->getOne($sSelect, false, false);
886  }
887 
895  public function getSqlActiveSnippet($blForceCoreTable = null)
896  {
897  $sQ = '';
898  $sTable = $this->getViewName($blForceCoreTable);
899 
900  // has 'active' field ?
901  if (isset($this->_aFieldNames['oxactive'])) {
902  $sQ = " $sTable.oxactive = 1 ";
903  }
904 
905  // has 'activefrom'/'activeto' fields ?
906  if (isset($this->_aFieldNames['oxactivefrom']) && isset($this->_aFieldNames['oxactiveto'])) {
907 
908  $sDate = date('Y-m-d H:i:s', oxRegistry::get('oxUtilsDate')->getTime());
909 
910  $sQ = $sQ ? " $sQ or " : '';
911  $sQ = " ( $sQ ( $sTable.oxactivefrom < '$sDate' and $sTable.oxactiveto > '$sDate' ) ) ";
912  }
913 
914  return $sQ;
915  }
916 
923  public function beforeUpdate($sOXID = null)
924  {
925  }
926 
935  public function onChange($iAction = null, $sOXID = null)
936  {
937  }
938 
939 
943  public function setInList()
944  {
945  $this->_blIsInList = true;
946  }
947 
953  protected function _isInList()
954  {
955  return $this->_blIsInList;
956  }
957 
966  protected function _getObjectViewName($sTable, $sShopID = null)
967  {
968 
969  return getViewName($sTable, -1, $sShopID);
970  }
971 
972 
983  protected function _getTableFields($sTable, $blReturnSimple = false)
984  {
985  $myUtils = oxRegistry::getUtils();
986 
987  $sCacheKey = $sTable . '_allfields_' . $blReturnSimple;
988  $aMetaFields = $myUtils->fromFileCache($sCacheKey);
989 
990  if ($aMetaFields) {
991  return $aMetaFields;
992  }
993 
994  $aMetaFields = oxDb::getInstance()->getTableDescription($sTable);
995 
996  if (!$blReturnSimple) {
997  $myUtils->toFileCache($sCacheKey, $aMetaFields);
998 
999  return $aMetaFields;
1000  }
1001 
1002  //returning simple array
1003  $aRet = array();
1004  if (is_array($aMetaFields)) {
1005  foreach ($aMetaFields as $oVal) {
1006  $aRet[strtolower($oVal->name)] = 0;
1007  }
1008  }
1009 
1010  $myUtils->toFileCache($sCacheKey, $aRet);
1011 
1012  return $aRet;
1013  }
1014 
1026  protected function _getAllFields($blReturnSimple = false)
1027  {
1028  if (!$this->getCoreTableName()) {
1029  return array();
1030  }
1031 
1032  return $this->_getTableFields($this->getCoreTableName(), $blReturnSimple);
1033  }
1034 
1041  protected function _initDataStructure($blForceFullStructure = false)
1042  {
1043  $myUtils = oxRegistry::getUtils();
1044 
1045  //get field names from cache
1046  $aFieldNames = null;
1047  $sFullCacheKey = 'fieldnames_' . $this->getCoreTableName() . '_' . $this->_sCacheKey;
1048  if ($this->_sCacheKey && !$this->_isDisabledFieldCache()) {
1049  $aFieldNames = $myUtils->fromFileCache($sFullCacheKey);
1050  }
1051 
1052  if (!$aFieldNames) {
1053  $aFieldNames = $this->_getNonCachedFieldNames($blForceFullStructure);
1054  if ($this->_sCacheKey && !$this->_isDisabledFieldCache()) {
1055  $myUtils->toFileCache($sFullCacheKey, $aFieldNames);
1056  }
1057  }
1058 
1059  if ($aFieldNames !== false) {
1060  foreach ($aFieldNames as $sField => $sStatus) {
1061  $this->_addField($sField, $sStatus);
1062  }
1063  }
1064  }
1065 
1077  protected function _getNonCachedFieldNames($blForceFullStructure = false)
1078  {
1079  //T2008-02-22
1080  //so if this method is executed on cached version we see it when profiling
1081  startProfile('!__CACHABLE__!');
1082 
1083  //case 1. (admin)
1084  if ($this->isAdmin()) {
1085  $aMetaFields = $this->_getAllFields();
1086  foreach ($aMetaFields as $oField) {
1087  if ($oField->max_length == -1) {
1088  $oField->max_length = 10; // double or float
1089  }
1090 
1091  if ($oField->type == 'datetime') {
1092  $oField->max_length = 20;
1093  }
1094 
1095  $this->_addField($oField->name, $this->_getFieldStatus($oField->name), $oField->type, $oField->max_length);
1096  }
1097  stopProfile('!__CACHABLE__!');
1098 
1099  return false;
1100  }
1101 
1102  //case 2. (just get all fields)
1103  if ($blForceFullStructure || !$this->_blUseLazyLoading) {
1104  $aMetaFields = $this->_getAllFields(true);
1105  /*
1106  foreach ( $aMetaFields as $sFieldName => $sVal) {
1107  $this->_addField( $sFieldName, $this->_getFieldStatus($sFieldName));
1108  }*/
1109  stopProfile('!__CACHABLE__!');
1110 
1111  return $aMetaFields;
1112  }
1113 
1114  //case 3. (get only oxid field, so we can fetch the rest of the fields over lazy loading mechanism)
1115  stopProfile('!__CACHABLE__!');
1116 
1117  return array('oxid' => 0);
1118  }
1119 
1128  protected function _getFieldStatus($sFieldName)
1129  {
1130  return 0;
1131  }
1132 
1143  protected function _addField($sName, $iStatus, $sType = null, $sLength = null)
1144  {
1145  //preparation
1146  $sName = strtolower($sName);
1147 
1148  //adding field names element
1149  $this->_aFieldNames[$sName] = $iStatus;
1150 
1151  //already set?
1152  $sLongName = $this->_getFieldLongName($sName);
1153  if (isset($this->$sLongName)) {
1154  return;
1155  }
1156 
1157  //defining the field
1158  $oField = false;
1159 
1160  if (isset($sType)) {
1161  $oField = new oxField();
1162  $oField->fldtype = $sType;
1163  //T2008-01-29
1164  //can't clone as the fields are objects and are not fully cloned
1165  $this->_blIsSimplyClonable = false;
1166  }
1167 
1168  if (isset($sLength)) {
1169  if (!$oField) {
1170  $oField = new oxField();
1171  }
1172  $oField->fldmax_length = $sLength;
1173  $this->_blIsSimplyClonable = false;
1174  }
1175 
1176  $this->$sLongName = $oField;
1177  }
1178 
1186  protected function _getFieldLongName($sFieldName)
1187  {
1188  //trying to avoid strpos call as often as possible
1189  $sCoreTableName = $this->getCoreTableName();
1190  if ($sFieldName[2] == $sCoreTableName[2] && strpos($sFieldName, $sCoreTableName . '__') === 0) {
1191  return $sFieldName;
1192  }
1193 
1194  return $sCoreTableName . '__' . strtolower($sFieldName);
1195  }
1196 
1206  protected function _setFieldData($sFieldName, $sValue, $iDataType = oxField::T_TEXT)
1207  {
1208 
1209  $sLongFieldName = $this->_getFieldLongName($sFieldName);
1210  //$sLongFieldName = $this->_sCoreTable . "__" . strtolower($sFieldName);
1211 
1212  //T2008-03-14
1213  //doing this because in lazy loaded lists on first load it is harmful to have initialised fields but not yet set
1214  //situation: only first article is loaded fully for "select oxid from oxarticles"
1215  /*
1216  if ($this->_blUseLazyLoading && !isset($this->$sLongFieldName))
1217  return;*/
1218 
1219  //in non lazy loading case we just add a field and do not care about it more
1220  if (!$this->_blUseLazyLoading && !isset($this->$sLongFieldName)) {
1221  $aFields = $this->_getAllFields(true);
1222  if (isset($aFields[strtolower($sFieldName)])) {
1223  $this->_addField($sFieldName, $this->_getFieldStatus($sFieldName));
1224  }
1225  }
1226  // if we have a double field we replace "," with "." in case somebody enters it in european format
1227  if (isset($this->$sLongFieldName) && isset($this->$sLongFieldName->fldtype) && $this->$sLongFieldName->fldtype == 'double') {
1228  $sValue = str_replace(',', '.', $sValue);
1229  }
1230 
1231  // isset is REQUIRED here not to use getter
1232  if (isset($this->$sLongFieldName) && is_object($this->$sLongFieldName)) {
1233  $this->$sLongFieldName->setValue($sValue, $iDataType);
1234  } else {
1235  $this->$sLongFieldName = new oxField($sValue, $iDataType);
1236  }
1237 
1238  }
1239 
1247  protected function _canFieldBeNull($sFieldName)
1248  {
1249  $aMetaData = $this->_getAllFields();
1250  foreach ($aMetaData as $oMetaInfo) {
1251  if (strcasecmp($oMetaInfo->name, $sFieldName) == 0) {
1252  return !$oMetaInfo->not_null;
1253  }
1254  }
1255 
1256  return false;
1257  }
1258 
1266  protected function _getFieldDefaultValue($sFieldName)
1267  {
1268  $aMetaData = $this->_getAllFields();
1269  foreach ($aMetaData as $oMetaInfo) {
1270  if (strcasecmp($oMetaInfo->name, $sFieldName) == 0) {
1271  return $oMetaInfo->default_value;
1272  }
1273  }
1274 
1275  return false;
1276  }
1277 
1286  protected function _getUpdateFieldValue($sFieldName, $oField)
1287  {
1288  $mValue = null;
1289  if ($oField instanceof oxField) {
1290  $mValue = $oField->getRawValue();
1291  } elseif (isset($oField->value)) {
1292  $mValue = $oField->value;
1293  }
1294 
1295  $oDb = oxDb::getDb();
1296  //Check if this field value is null AND it can be null according if not returning default value
1297  if ((null === $mValue)) {
1298  if ($this->_canFieldBeNull($sFieldName)) {
1299  return 'null';
1300  } elseif ($mValue = $this->_getFieldDefaultValue($sFieldName)) {
1301  return $oDb->quote($mValue);
1302  }
1303  }
1304 
1305  return $oDb->quote($mValue);
1306  }
1307 
1316  protected function _getUpdateFields($blUseSkipSaveFields = true)
1317  {
1318  $sSql = '';
1319  $blSep = false;
1320 
1321  foreach (array_keys($this->_aFieldNames) as $sKey) {
1322  $sLongName = $this->_getFieldLongName($sKey);
1323  $oField = $this->$sLongName;
1324 
1325 
1326  if (!$blUseSkipSaveFields || ($blUseSkipSaveFields && !in_array(strtolower($sKey), $this->_aSkipSaveFields))) {
1327  $sSql .= (($blSep) ? ',' : '') . $sKey . ' = ' . $this->_getUpdateFieldValue($sKey, $oField);
1328  $blSep = true;
1329  }
1330  }
1331 
1332  return $sSql;
1333  }
1334 
1344  protected function _update()
1345  {
1346  //do not allow derived item update
1347  if (!$this->allowDerivedUpdate()) {
1348  return false;
1349  }
1350 
1351 
1352  if (!$this->getId()) {
1356  $oEx = oxNew('oxObjectException');
1357  $oEx->setMessage('EXCEPTION_OBJECT_OXIDNOTSET');
1358  $oEx->setObject($this);
1359  throw $oEx;
1360  }
1361  $sCoreTableName = $this->getCoreTableName();
1362 
1363  $sIDKey = oxRegistry::getUtils()->getArrFldName($sCoreTableName . '.oxid');
1364  $this->$sIDKey = new oxField($this->getId(), oxField::T_RAW);
1365  $oDb = oxDb::getDb();
1366 
1367  $sUpdate = "update {$sCoreTableName} set " . $this->_getUpdateFields()
1368  . " where {$sCoreTableName}.oxid = " . $oDb->quote($this->getId());
1369 
1370  //trigger event
1371  $this->beforeUpdate();
1372 
1373  $blRet = (bool) $oDb->execute($sUpdate);
1374 
1375  return $blRet;
1376  }
1377 
1385  protected function _insert()
1386  {
1387 
1389  $myConfig = $this->getConfig();
1390  $myUtils = oxRegistry::getUtils();
1391 
1392  // let's get a new ID
1393  if (!$this->getId()) {
1394  $this->setId();
1395  }
1396 
1397  $sIDKey = $myUtils->getArrFldName($this->getCoreTableName() . '.oxid');
1398  $this->$sIDKey = new oxField($this->getId(), oxField::T_RAW);
1399  $sInsert = "Insert into {$this->getCoreTableName()} set ";
1400 
1401  //setting oxshopid
1402  $sShopField = $myUtils->getArrFldName($this->getCoreTableName() . '.oxshopid');
1403 
1404  if (isset($this->$sShopField) && !$this->$sShopField->value) {
1405  $this->$sShopField = new oxField($myConfig->getShopId(), oxField::T_RAW);
1406  }
1407 
1408  $sInsert .= $this->_getUpdateFields($this->getUseSkipSaveFields());
1409 
1410  $blRet = (bool) $oDb->execute($sInsert);
1411 
1412 
1413  return $blRet;
1414  }
1415 
1416 
1423  protected function _isDisabledFieldCache()
1424  {
1425  $sClass = get_class($this);
1426  if (isset(self::$_blDisableFieldCaching[$sClass]) && self::$_blDisableFieldCaching[$sClass]) {
1427  return true;
1428  }
1429 
1430  return false;
1431  }
1432 
1436  protected function _addSkippedSaveFieldsForMapping()
1437  {
1438  }
1439 
1443  protected function _disableLazyLoadingForCaching()
1444  {
1445  }
1446 
1452  public function isOx()
1453  {
1454  $sOxId = $this->getId();
1455  if ($sOxId[0] == 'o' && $sOxId[1] == 'x') {
1456  return true;
1457  }
1458 
1459  return false;
1460  }
1461 
1467  public function isReadOnly()
1468  {
1469  return $this->_blReadOnly;
1470  }
1471 
1477  public function setReadOnly($blReadOnly)
1478  {
1479  $this->_blReadOnly = $blReadOnly;
1480  }
1481 
1487  public function getFieldNames()
1488  {
1489  return array_keys($this->_aFieldNames);
1490  }
1491 
1497  public function addFieldName($sName)
1498  {
1499  //preparation
1500  $sName = strtolower($sName);
1501  $this->_aFieldNames[$sName] = 0;
1502  }
1503 
1509  public function getLanguage()
1510  {
1511  return -1;
1512  }
1513 
1514 }