OXID eShop CE  4.8.12
 All Classes 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 {
22  protected $_sOXID = null;
23 
28  protected $_iShopId = null;
29 
35  protected $_blIsSimplyClonable = true;
36 
41  protected $_sClassName = 'oxbase';
42 
48  protected $_sCoreTable = null;
49 
54  protected $_sViewTable = null;
55 
56 
62  protected $_aFieldNames = array('oxid' => 0);
63 
69  protected $_sCacheKey = null;
70 
76  protected $_blUseLazyLoading = false;
77 
83  protected $_aSkipSaveFields = array('oxtimestamp');
84 
90  protected $_blUseSkipSaveFields = true;
91 
96  protected $_sExistKey = 'oxid';
97 
104  protected $_blIsDerived = null;
105 
115  protected static $_blDisableFieldCaching = array();
116 
122  protected $_blIsSeoObject = false;
123 
129  protected $_blUpdateSeo = true;
130 
136  protected $_blReadOnly = false;
137 
143  protected $_blIsInList = false;
144 
150  protected $_isLoaded = false;
151 
157  protected $_aInnerLazyCache = null;
158 
164  protected $_blEmployMultilanguage = false;
165 
166 
172  public function getUseSkipSaveFields()
173  {
175  }
176 
184  public function setUseSkipSaveFields( $blUseSkipSaveFields )
185  {
186  $this->_blUseSkipSaveFields = $blUseSkipSaveFields;
187  }
188 
192  public function __construct()
193  {
194  // set active shop
195  $myConfig = $this->getConfig();
196  $this->_sCacheKey = $this->getViewName();
197 
198 
199  if ( $this->_blUseLazyLoading ) {
200  $this->_sCacheKey .= $myConfig->getActiveView()->getClassName();
201  } else {
202  $this->_sCacheKey .= 'allviews';
203  }
204 
205  //do not cache for admin?
206  if ( $this->isAdmin() ) {
207  $this->_sCacheKey = null;
208  }
209 
210  $this->setShopId( $myConfig->getShopId() );
211  }
212 
221  public function __set( $sName, $sValue )
222  {
223  $this->$sName = $sValue;
224  if ( $this->_blUseLazyLoading && strpos( $sName, $this->_sCoreTable . '__' ) === 0 ) {
225  $sFieldName = str_replace( $this->_sCoreTable . "__", '', $sName );
226  if ( $sFieldName != 'oxnid' && ( !isset( $this->_aFieldNames[$sFieldName] ) || !$this->_aFieldNames[$sFieldName] ) ) {
227  $aAllFields = $this->_getAllFields(true);
228  if ( isset( $aAllFields[strtolower($sFieldName)] ) ) {
229  $iFieldStatus = $this->_getFieldStatus( $sFieldName );
230  $this->_addField( $sFieldName, $iFieldStatus );
231  }
232  }
233  }
234  }
235 
243  public function __get( $sName )
244  {
245  switch ( $sName ) {
246  case 'blIsDerived':
247  return $this->isDerived();
248  break;
249  case 'sOXID':
250  return $this->getId();
251  break;
252  case 'blReadOnly':
253  return $this->isReadOnly();
254  break;
255  }
256 
257  // implementing lazy loading fields
258  // This part of the code is slow and normally is called before field cache is built.
259  // Make sure it is not called after first page is loaded and cache data is fully built.
260  if ( $this->_blUseLazyLoading && stripos( $sName, $this->_sCoreTable . "__" ) === 0 ) {
261 
262  if ( $this->getId() ) {
263 
264  //lazy load it
265  $sFieldName = str_replace( $this->_sCoreTable . '__', '', $sName );
266  $sCacheFieldName = strtoupper( $sFieldName );
267 
268  $iFieldStatus = $this->_getFieldStatus( $sFieldName );
269  $sViewName = $this->getViewName();
270  $sId = $this->getId();
271 
272  try {
273  if ( $this->_aInnerLazyCache === null ) {
274 
276  $sQ = 'SELECT * FROM ' . $sViewName . ' WHERE `oxid` = ' . $oDb->quote( $sId );
277  $rs = $oDb->select( $sQ );
278  if ( $rs && $rs->RecordCount() ) {
279  $this->_aInnerLazyCache = array_change_key_case( $rs->fields, CASE_UPPER );
280  if ( array_key_exists( $sCacheFieldName, $this->_aInnerLazyCache ) ) {
281  $sFieldValue = $this->_aInnerLazyCache[$sCacheFieldName];
282  } else {
283  return null;
284  }
285  } else {
286  return null;
287  }
288  } elseif ( array_key_exists( $sCacheFieldName, $this->_aInnerLazyCache ) ) {
289  $sFieldValue = $this->_aInnerLazyCache[$sCacheFieldName];
290  } else {
291  return null;
292  }
293 
294  $this->_addField( $sFieldName, $iFieldStatus );
295  $this->_setFieldData( $sFieldName, $sFieldValue );
296 
297  //save names to cache for next loading
298  if ($this->_sCacheKey) {
299  $myUtils = oxRegistry::getUtils();
300  $sCacheKey = 'fieldnames_' . $this->_sCoreTable . '_' . $this->_sCacheKey;
301  $aFieldNames = $myUtils->fromFileCache( $sCacheKey );
302  $aFieldNames[$sFieldName] = $iFieldStatus;
303  $myUtils->toFileCache( $sCacheKey, $aFieldNames );
304  }
305  } catch ( Exception $e ) {
306  return null;
307  }
308 
309  //do not use field cache for this page
310  //as if we use it for lists then objects are loaded empty instead of lazy loading.
311  self::$_blDisableFieldCaching[get_class( $this )] = true;
312  }
313 
314  oxUtilsObject::getInstance()->resetInstanceCache(get_class($this));
315  }
316 
317  //returns stdClass implementing __toString() method due to uknown scenario where this var should be used.
318  if (!isset( $this->$sName ) ) {
319  $this->$sName = null;
320  }
321 
322  return $this->$sName;
323  }
324 
332  public function __isset($mVar)
333  {
334  return isset($this->$mVar);
335  }
336 
342  public function __clone()
343  {
344  if (!$this->_blIsSimplyClonable) {
345  foreach ( $this->_aFieldNames as $sField => $sVal ) {
346  $sLongName = $this->_getFieldLongName( $sField );
347  if ( is_object($this->$sLongName)) {
348  $this->$sLongName = clone $this->$sLongName;
349  }
350  }
351  }
352  }
353 
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 
424  public function init( $sTableName = null, $blForceAllFields = false )
425  {
426  if ( $sTableName ) {
427  $this->_sCoreTable = $sTableName;
428  }
429 
430  // reset view table
431  $this->_sViewTable = false;
432 
433  if ( count( $this->_aFieldNames ) <= 1 ) {
434  $this->_initDataStructure( $blForceAllFields );
435  }
436  }
437 
445  public function assign( $dbRecord )
446  {
447  if ( !is_array( $dbRecord ) ) {
448  return;
449  }
450 
451 
452  reset($dbRecord );
453  while ( list( $sName, $sValue ) = each( $dbRecord ) ) {
454 
455  // patch for IIS
456  //TODO: test it on IIS do we still need it
457  //if( is_array($value) && count( $value) == 1)
458  // $value = current( $value);
459 
460  $this->_setFieldData( $sName, $sValue );
461  }
462 
463  $sOxidField = $this->_getFieldLongName( 'oxid' );
464  $this->_sOXID = $this->$sOxidField->value;
465 
466  }
467 
473  public function getClassName()
474  {
475  return $this->_sClassName;
476  }
477 
483  public function getCoreTableName()
484  {
485  return $this->_sCoreTable;
486  }
487 
493  public function getId()
494  {
495  return $this->_sOXID;
496  }
497 
505  public function setId( $sOXID = null )
506  {
507  if ( $sOXID ) {
508  $this->_sOXID = $sOXID;
509  } else {
510  $this->_sOXID = oxUtilsObject::getInstance()->generateUID();
511  }
512 
513  $sIdVarName = $this->_sCoreTable . '__oxid';
514  $this->$sIdVarName = new oxField($this->_sOXID, oxField::T_RAW);
515 
516  return $this->_sOXID;
517  }
518 
526  public function setShopId( $iShopId )
527  {
528  $this->_iShopId = $iShopId;
529  }
530 
536  public function getShopId()
537  {
538  return $this->_iShopId;
539  }
540 
548  public function getViewName( $blForceCoreTableUsage = null )
549  {
550  if (!$this->_sViewTable || ( $blForceCoreTableUsage !== null )) {
551  if ( $blForceCoreTableUsage === true ) {
552  return $this->_sCoreTable;
553  }
554 
555 
556  if ( ( $blForceCoreTableUsage !== null ) && $blForceCoreTableUsage ) {
557  $iShopId = -1;
558  } else {
559  $iShopId = oxRegistry::getConfig()->getShopId();
560  }
561 
562  $sViewName = getViewName( $this->_sCoreTable, $this->_blEmployMultilanguage == false ? -1 : $this->getLanguage(), $iShopId );
563  if ( $blForceCoreTableUsage !== null ) {
564  return $sViewName;
565  }
566  $this->_sViewTable = $sViewName;
567  }
568  return $this->_sViewTable;
569  }
570 
579  public function modifyCacheKey( $sCacheKey, $blOverride = false )
580  {
581  if ( $blOverride ) {
582  $this->_sCacheKey = $sCacheKey;
583  } else {
584  $this->_sCacheKey .= $sCacheKey;
585  }
586  }
587 
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 
618  public function setIsDerived( $blVal )
619  {
620  $this->_blIsDerived = $blVal;
621  }
622 
629  public function isMultilang()
630  {
631  return false;
632  }
633 
643  public function load( $sOXID )
644  {
645 
646  //getting at least one field before lazy loading the object
647  $this->_addField( 'oxid', 0 );
648  $sSelect = $this->buildSelectString( array( $this->getViewName() . '.oxid' => $sOXID) );
649  $this->_isLoaded = $this->assignRecord( $sSelect );
650 
651 
652  return $this->_isLoaded;
653  }
654 
660  public function isLoaded()
661  {
662  return $this->_isLoaded;
663  }
664 
672  public function buildSelectString( $aWhere = null)
673  {
674  $oDB = oxDb::getDb();
675 
676  $sGet = $this->getSelectFields();
677  $sSelect = "select $sGet from " . $this->getViewName() . ' where 1 ';
678 
679  if ( $aWhere) {
680  reset($aWhere);
681  while (list($name, $value) = each($aWhere)) {
682  $sSelect .= ' and ' . $name . ' = '.$oDB->quote($value);
683  }
684  }
685 
686  // add active shop
687 
688  return $sSelect;
689  }
690 
698  public function assignRecord( $sSelect )
699  {
700  $blRet = false;
701 
702  $rs = oxDb::getDb( oxDb::FETCH_MODE_ASSOC )->select( $sSelect );
703 
704  if ($rs != false && $rs->recordCount() > 0) {
705  $blRet = true;
706  $this->assign( $rs->fields);
707  }
708 
709  return $blRet;
710  }
711 
719  public function getFieldData( $sFieldName )
720  {
721  $sLongFieldName = $this->_getFieldLongName( $sFieldName );
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  return $sSelectFields;
749  }
750 
758  public function delete( $sOXID = null)
759  {
760  if ( !$sOXID ) {
761  $sOXID = $this->getId();
762 
763  //do not allow derived deletion
764  if ( !$this->allowDerivedDelete() ) {
765  return false;
766  }
767  }
768 
769  if ( !$sOXID ) {
770  return false;
771  }
772 
773 
775  $sDelete = "delete from $this->_sCoreTable where oxid = " . $oDB->quote( $sOXID );
776  $oDB->execute( $sDelete );
777  if ( $blDelete = ( bool ) $oDB->affected_Rows() ) {
778  $this->onChange( ACTION_DELETE, $sOXID );
779  }
780 
781  return $blDelete;
782  }
783 
784 
790  public function save()
791  {
792  if ( !is_array( $this->_aFieldNames ) ) {
793  return false;
794  }
795 
796  // #739A - should be executed here because of date/time formatting feature
797  if ( $this->isAdmin() && !$this->getConfig()->getConfigParam( 'blSkipFormatConversion' ) ) {
798  foreach ($this->_aFieldNames as $sName => $sVal) {
799  $sLongName = $this->_getFieldLongName($sName);
800  if ( isset($this->$sLongName->fldtype) && $this->$sLongName->fldtype == 'datetime' ) {
801  oxRegistry::get('oxUtilsDate')->convertDBDateTime( $this->$sLongName, true );
802  } elseif ( isset($this->$sLongName->fldtype) && $this->$sLongName->fldtype == 'timestamp' ) {
803  oxRegistry::get('oxUtilsDate')->convertDBTimestamp( $this->$sLongName, true );
804  } elseif ( isset($this->$sLongName->fldtype) && $this->$sLongName->fldtype == 'date' ) {
805  oxRegistry::get('oxUtilsDate')->convertDBDate( $this->$sLongName, true );
806  }
807  }
808  }
809  if ( $this->exists() ) {
810  //do not allow derived update
811  if ( !$this->allowDerivedUpdate() ) {
812  return false;
813  }
814 
815  $blRet = $this->_update();
816  $sAction = ACTION_UPDATE;
817  } else {
818  $blRet = $this->_insert();
819  $sAction = ACTION_INSERT;
820  }
821 
822  $this->onChange($sAction);
823 
824  if ( $blRet ) {
825  return $this->getId();
826  } else {
827  return false;
828  }
829  }
830 
836  public function allowDerivedUpdate()
837  {
838  return !$this->isDerived();
839  }
840 
846  public function allowDerivedDelete()
847  {
848  return !$this->isDerived();
849  }
850 
858  public function exists( $sOXID = null)
859  {
860  if ( !$sOXID ) {
861  $sOXID = $this->getId();
862  }
863  if ( !$sOXID ) {
864  return false;
865  }
866 
867  $sViewName = $this->getCoreTableName();
869  $sSelect= "select {$this->_sExistKey} from {$sViewName} where {$this->_sExistKey} = " . $oDb->quote( $sOXID );
870 
871  return ( bool ) $oDb->getOne( $sSelect, false, false );
872  }
873 
881  public function getSqlActiveSnippet( $blForceCoreTable = null )
882  {
883  $sQ = '';
884  $sTable = $this->getViewName($blForceCoreTable);
885 
886  // has 'active' field ?
887  if ( isset( $this->_aFieldNames['oxactive'] ) ) {
888  $sQ = " $sTable.oxactive = 1 ";
889  }
890 
891  // has 'activefrom'/'activeto' fields ?
892  if ( isset( $this->_aFieldNames['oxactivefrom'] ) && isset( $this->_aFieldNames['oxactiveto'] ) ) {
893 
894  $sDate = date( 'Y-m-d H:i:s', oxRegistry::get('oxUtilsDate')->getTime() );
895 
896  $sQ = $sQ ? " $sQ or " : '';
897  $sQ = " ( $sQ ( $sTable.oxactivefrom < '$sDate' and $sTable.oxactiveto > '$sDate' ) ) ";
898  }
899 
900  return $sQ;
901  }
902 
911  public function beforeUpdate( $sOXID = null )
912  {
913  }
914 
925  public function onChange( $iAction = null, $sOXID = null )
926  {
927  }
928 
929 
935  public function setInList()
936  {
937  $this->_blIsInList = true;
938  }
939 
945  protected function _isInList()
946  {
947  return $this->_blIsInList;
948  }
949 
958  protected function _getObjectViewName( $sTable, $sShopID = null )
959  {
960  return getViewName( $sTable, -1, $sShopID);
961  }
962 
963 
974  protected function _getTableFields($sTable, $blReturnSimple = false )
975  {
976  $myUtils = oxRegistry::getUtils();
977 
978  $sCacheKey = $sTable . '_allfields_' . $blReturnSimple;
979  $aMetaFields = $myUtils->fromFileCache( $sCacheKey );
980 
981  if ( $aMetaFields ) {
982  return $aMetaFields;
983  }
984 
985  $aMetaFields = oxDb::getInstance()->getTableDescription( $sTable );
986 
987  if ( !$blReturnSimple ) {
988  $myUtils->toFileCache( $sCacheKey, $aMetaFields );
989  return $aMetaFields;
990  }
991 
992  //returning simple array
993  $aRet = array();
994  if (is_array($aMetaFields)) {
995  foreach ( $aMetaFields as $oVal ) {
996  $aRet[strtolower( $oVal->name )] = 0;
997  }
998  }
999 
1000  $myUtils->toFileCache( $sCacheKey, $aRet);
1001 
1002  return $aRet;
1003  }
1004 
1016  protected function _getAllFields($blReturnSimple = false )
1017  {
1018  if (!$this->_sCoreTable) {
1019  return array();
1020  }
1021  return $this->_getTableFields($this->_sCoreTable, $blReturnSimple);
1022  }
1023 
1032  protected function _initDataStructure($blForceFullStructure = false )
1033  {
1034  $myUtils = oxRegistry::getUtils();
1035 
1036  //get field names from cache
1037  $aFieldNames = null;
1038  $sFullCacheKey = 'fieldnames_' . $this->_sCoreTable . '_' . $this->_sCacheKey;
1039  if ($this->_sCacheKey && !$this->_isDisabledFieldCache()) {
1040  $aFieldNames = $myUtils->fromFileCache( $sFullCacheKey );
1041  }
1042 
1043  if (!$aFieldNames) {
1044  $aFieldNames = $this->_getNonCachedFieldNames( $blForceFullStructure );
1045  if ($this->_sCacheKey && !$this->_isDisabledFieldCache()) {
1046  $myUtils->toFileCache( $sFullCacheKey, $aFieldNames );
1047  }
1048  }
1049 
1050  if ( $aFieldNames !== false ) {
1051  foreach ( $aFieldNames as $sField => $sStatus ) {
1052  $this->_addField( $sField, $sStatus );
1053  }
1054  }
1055  }
1056 
1068  protected function _getNonCachedFieldNames( $blForceFullStructure = false )
1069  {
1070  //T2008-02-22
1071  //so if this method is executed on cached version we see it when profiling
1072  startProfile('!__CACHABLE__!');
1073 
1074  //case 1. (admin)
1075  if ($this->isAdmin()) {
1076  $aMetaFields = $this->_getAllFields();
1077  foreach ( $aMetaFields as $oField ) {
1078  if ( $oField->max_length == -1 ) {
1079  $oField->max_length = 10; // double or float
1080  }
1081 
1082  if ( $oField->type == 'datetime' ) {
1083  $oField->max_length = 20;
1084  }
1085 
1086  $this->_addField( $oField->name, $this->_getFieldStatus($oField->name), $oField->type, $oField->max_length );
1087  }
1088  stopProfile('!__CACHABLE__!');
1089  return false;
1090  }
1091 
1092  //case 2. (just get all fields)
1093  if ( $blForceFullStructure || !$this->_blUseLazyLoading ) {
1094  $aMetaFields = $this->_getAllFields(true);
1095  /*
1096  foreach ( $aMetaFields as $sFieldName => $sVal) {
1097  $this->_addField( $sFieldName, $this->_getFieldStatus($sFieldName));
1098  }*/
1099  stopProfile('!__CACHABLE__!');
1100  return $aMetaFields;
1101  }
1102 
1103  //case 3. (get only oxid field, so we can fetch the rest of the fields over lazy loading mechanism)
1104  stopProfile('!__CACHABLE__!');
1105  return array('oxid' => 0);
1106  }
1107 
1116  protected function _getFieldStatus( $sFieldName )
1117  {
1118  return 0;
1119  }
1120 
1131  protected function _addField($sName, $iStatus, $sType = null, $sLength = null )
1132  {
1133  //preparation
1134  $sName = strtolower( $sName );
1135 
1136  //adding field names element
1137  $this->_aFieldNames[$sName] = $iStatus;
1138 
1139  //already set?
1140  $sLongName = $this->_getFieldLongName( $sName );
1141  if ( isset($this->$sLongName) ) {
1142  return;
1143  }
1144 
1145  //defining the field
1146  $oField = false;
1147 
1148  if ( isset( $sType ) ) {
1149  $oField = new oxField();
1150  $oField->fldtype = $sType;
1151  //T2008-01-29
1152  //can't clone as the fields are objects and are not fully cloned
1153  $this->_blIsSimplyClonable = false;
1154  }
1155 
1156  if ( isset( $sLength ) ) {
1157  if ( !$oField ) {
1158  $oField = new oxField();
1159  }
1160  $oField->fldmax_length = $sLength;
1161  $this->_blIsSimplyClonable = false;
1162  }
1163 
1164  $this->$sLongName = $oField;
1165  }
1166 
1174  protected function _getFieldLongName( $sFieldName )
1175  {
1176  //trying to avoid strpos call as often as possible
1177  if ( $sFieldName[2] == $this->_sCoreTable[2] && strpos( $sFieldName, $this->_sCoreTable . '__' ) === 0 ) {
1178  return $sFieldName;
1179  }
1180 
1181  return $this->_sCoreTable . '__' . strtolower( $sFieldName );
1182  }
1183 
1193  protected function _setFieldData( $sFieldName, $sValue, $iDataType = oxField::T_TEXT )
1194  {
1195 
1196  $sLongFieldName = $this->_getFieldLongName( $sFieldName);
1197  //$sLongFieldName = $this->_sCoreTable . "__" . strtolower($sFieldName);
1198 
1199  //T2008-03-14
1200  //doing this because in lazy loaded lists on first load it is harmful to have initialised fields but not yet set
1201  //situation: only first article is loaded fully for "select oxid from oxarticles"
1202  /*
1203  if ($this->_blUseLazyLoading && !isset($this->$sLongFieldName))
1204  return;*/
1205 
1206  //in non lazy loading case we just add a field and do not care about it more
1207  if (!$this->_blUseLazyLoading && !isset( $this->$sLongFieldName )) {
1208  $aFields = $this->_getAllFields(true);
1209  if ( isset( $aFields[strtolower( $sFieldName )] ) ) {
1210  $this->_addField( $sFieldName, $this->_getFieldStatus( $sFieldName ) );
1211  }
1212  }
1213  // if we have a double field we replace "," with "." in case somebody enters it in european format
1214  if (isset($this->$sLongFieldName) && isset( $this->$sLongFieldName->fldtype ) && $this->$sLongFieldName->fldtype == 'double') {
1215  $sValue = str_replace( ',', '.', $sValue );
1216  }
1217 
1218  // isset is REQUIRED here not to use getter
1219  if ( isset( $this->$sLongFieldName ) && is_object( $this->$sLongFieldName ) ) {
1220  $this->$sLongFieldName->setValue( $sValue, $iDataType );
1221  } else {
1222  $this->$sLongFieldName = new oxField( $sValue, $iDataType );
1223  }
1224 
1225  }
1226 
1234  protected function _canFieldBeNull( $sFieldName )
1235  {
1236  $aMetaData = $this->_getAllFields();
1237  foreach ( $aMetaData as $oMetaInfo ) {
1238  if ( strcasecmp( $oMetaInfo->name, $sFieldName ) == 0 ) {
1239  return !$oMetaInfo->not_null;
1240  }
1241  }
1242  return false;
1243  }
1244 
1252  protected function _getFieldDefaultValue( $sFieldName )
1253  {
1254  $aMetaData = $this->_getAllFields();
1255  foreach ( $aMetaData as $oMetaInfo ) {
1256  if ( strcasecmp( $oMetaInfo->name, $sFieldName ) == 0 ) {
1257  return $oMetaInfo->default_value;
1258  }
1259  }
1260  return false;
1261  }
1262 
1271  protected function _getUpdateFieldValue( $sFieldName, $oField )
1272  {
1273  $mValue = null;
1274  if ( $oField instanceof oxField ) {
1275  $mValue = $oField->getRawValue();
1276  } elseif ( isset( $oField->value ) ) {
1277  $mValue = $oField->value;
1278  }
1279 
1280  $oDb = oxDb::getDb();
1281  //Check if this field value is null AND it can be null according if not returning default value
1282  if ( ( null === $mValue ) ) {
1283  if ( $this->_canFieldBeNull( $sFieldName ) ) {
1284  return 'null';
1285  } elseif ( $mValue = $this->_getFieldDefaultValue( $sFieldName ) ) {
1286  return $oDb->quote( $mValue );
1287  }
1288  }
1289 
1290  return $oDb->quote( $mValue );
1291  }
1292 
1301  protected function _getUpdateFields( $blUseSkipSaveFields = true )
1302  {
1303  $sSql = '';
1304  $blSep = false;
1305 
1306  foreach ( array_keys( $this->_aFieldNames ) as $sKey ) {
1307  $sLongName = $this->_getFieldLongName( $sKey );
1308  $oField = $this->$sLongName;
1309 
1310 
1311  if ( !$blUseSkipSaveFields || ( $blUseSkipSaveFields && !in_array( strtolower( $sKey ), $this->_aSkipSaveFields ) ) ) {
1312  $sSql .= (( $blSep) ? ',' : '' ) . $sKey . ' = ' . $this->_getUpdateFieldValue( $sKey, $oField );
1313  $blSep = true;
1314  }
1315  }
1316 
1317  return $sSql;
1318  }
1319 
1329  protected function _update()
1330  {
1331  //do not allow derived item update
1332  if ( !$this->allowDerivedUpdate() ) {
1333  return false;
1334  }
1335 
1336 
1337  if ( !$this->getId() ) {
1341  $oEx = oxNew( 'oxObjectException' );
1342  $oEx->setMessage( 'EXCEPTION_OBJECT_OXIDNOTSET' );
1343  $oEx->setObject($this);
1344  throw $oEx;
1345  }
1346 
1347  $sIDKey = oxRegistry::getUtils()->getArrFldName( $this->_sCoreTable . '.oxid' );
1348  $this->$sIDKey = new oxField($this->getId(), oxField::T_RAW);
1349  $oDb = oxDb::getDb();
1350 
1351  $sUpdate= "update {$this->_sCoreTable} set " . $this->_getUpdateFields()
1352  ." where {$this->_sCoreTable}.oxid = " . $oDb->quote( $this->getId() );
1353 
1354  //trigger event
1355  $this->beforeUpdate();
1356 
1357  $blRet = (bool) $oDb->execute( $sUpdate );
1358 
1359  return $blRet;
1360  }
1361 
1369  protected function _insert()
1370  {
1371 
1373  $myConfig = $this->getConfig();
1374  $myUtils = oxRegistry::getUtils();
1375 
1376  // let's get a new ID
1377  if ( !$this->getId()) {
1378  $this->setId();
1379  }
1380 
1381  $sIDKey = $myUtils->getArrFldName( $this->_sCoreTable . '.oxid' );
1382  $this->$sIDKey = new oxField( $this->getId(), oxField::T_RAW );
1383  $sInsert = "Insert into {$this->_sCoreTable} set ";
1384 
1385  //setting oxshopid
1386  $sShopField = $myUtils->getArrFldName( $this->_sCoreTable . '.oxshopid' );
1387 
1388  if ( isset( $this->$sShopField ) && !$this->$sShopField->value ) {
1389  $this->$sShopField = new oxField( $myConfig->getShopId(), oxField::T_RAW );
1390  }
1391 
1392 
1393  $sInsert .= $this->_getUpdateFields( $this->getUseSkipSaveFields() );
1394 
1395  $blRet = (bool) $oDb->execute( $sInsert );
1396 
1397  return $blRet;
1398  }
1399 
1406  protected function _isDisabledFieldCache()
1407  {
1408  $sClass = get_class( $this );
1409  if ( isset( self::$_blDisableFieldCaching[$sClass] ) && self::$_blDisableFieldCaching[$sClass] ) {
1410  return true;
1411  }
1412 
1413  return false;
1414  }
1415 
1421  public function isOx()
1422  {
1423  $sOxId = $this->getId();
1424  if ( $sOxId[0] == 'o' && $sOxId[1] == 'x' ) {
1425  return true;
1426  }
1427  return false;
1428  }
1429 
1435  public function isReadOnly()
1436  {
1437  return $this->_blReadOnly;
1438  }
1439 
1447  public function setReadOnly( $blReadOnly )
1448  {
1449  $this->_blReadOnly = $blReadOnly;
1450  }
1451 
1457  public function getFieldNames()
1458  {
1459  return array_keys( $this->_aFieldNames );
1460  }
1461 
1469  public function addFieldName( $sName )
1470  {
1471  //preparation
1472  $sName = strtolower( $sName );
1473  $this->_aFieldNames[$sName] = 0;
1474  }
1475 
1476 
1482  public function getLanguage()
1483  {
1484  return -1;
1485  }
1486 
1487 }