OXID eShop CE  4.10.7
 All Classes Namespaces Files Functions Variables Pages
oxarticlelist.php
Go to the documentation of this file.
1 <?php
2 
8 class oxArticleList extends oxList
9 {
10 
14  protected $_sCustomSorting;
15 
21  protected $_sObjectsInListName = 'oxarticle';
22 
28  protected $_blLoadSelectLists = false;
29 
35  public function setCustomSorting($sSorting)
36  {
37  $this->_sCustomSorting = $sSorting;
38  }
39 
43  public function enableSelectLists()
44  {
45  $this->_blLoadSelectLists = true;
46  }
47 
56  public function selectString($sSelect)
57  {
58  startProfile("loadinglists");
59  $oRes = parent::selectString($sSelect);
60  stopProfile("loadinglists");
61 
62  return $oRes;
63  }
64 
70  public function getHistoryArticles()
71  {
72  if ($aArticlesIds = $this->getSession()->getVariable('aHistoryArticles')) {
73  return $aArticlesIds;
74  } elseif ($sArticlesIds = oxRegistry::get("oxUtilsServer")->getOxCookie('aHistoryArticles')) {
75  return explode('|', $sArticlesIds);
76  }
77  }
78 
84  public function setHistoryArticles($aArticlesIds)
85  {
86  if ($this->getSession()->getId()) {
87  oxRegistry::getSession()->setVariable('aHistoryArticles', $aArticlesIds);
88  // clean cookie, if session started
89  oxRegistry::get("oxUtilsServer")->setOxCookie('aHistoryArticles', '');
90  } else {
91  oxRegistry::get("oxUtilsServer")->setOxCookie('aHistoryArticles', implode('|', $aArticlesIds));
92  }
93  }
94 
102  public function loadHistoryArticles($sArtId, $iCnt = 4)
103  {
104  $aHistoryArticles = $this->getHistoryArticles();
105  $aHistoryArticles[] = $sArtId;
106 
107  // removing dublicates
108  $aHistoryArticles = array_unique($aHistoryArticles);
109  if (count($aHistoryArticles) > ($iCnt + 1)) {
110  array_shift($aHistoryArticles);
111  }
112 
113  $this->setHistoryArticles($aHistoryArticles);
114 
115  //remove current article and return array
116  //asignment =, not ==
117  if (($iCurrentArt = array_search($sArtId, $aHistoryArticles)) !== false) {
118  unset($aHistoryArticles[$iCurrentArt]);
119  }
120 
121  $aHistoryArticles = array_values($aHistoryArticles);
122  $this->loadIds($aHistoryArticles);
123  $this->sortByIds($aHistoryArticles);
124  }
125 
131  public function sortByIds($aIds)
132  {
133  $this->_aOrderMap = array_flip($aIds);
134  uksort($this->_aArray, array($this, '_sortByOrderMapCallback'));
135  }
136 
147  protected function _sortByOrderMapCallback($key1, $key2)
148  {
149  if (isset($this->_aOrderMap[$key1])) {
150  if (isset($this->_aOrderMap[$key2])) {
151  $iDiff = $this->_aOrderMap[$key2] - $this->_aOrderMap[$key1];
152  if ($iDiff > 0) {
153  return -1;
154  } elseif ($iDiff < 0) {
155  return 1;
156  } else {
157  return 0;
158  }
159  } else {
160  // first is here, but 2nd is not - 1st gets more priority
161  return -1;
162  }
163  } elseif (isset($this->_aOrderMap[$key2])) {
164  // first is not here, but 2nd is - 2nd gets more priority
165  return 1;
166  } else {
167  // both unset, equal
168  return 0;
169  }
170  }
171 
177  public function loadNewestArticles($iLimit = null)
178  {
179  //has module?
180  $myConfig = $this->getConfig();
181 
182  if (!$myConfig->getConfigParam('bl_perfLoadPriceForAddList')) {
183  $this->getBaseObject()->disablePriceLoad();
184  }
185 
186  $this->_aArray = array();
187  switch ($myConfig->getConfigParam('iNewestArticlesMode')) {
188  case 0:
189  // switched off, do nothing
190  break;
191  case 1:
192  // manually entered
193  $this->loadActionArticles('oxnewest', $iLimit);
194  break;
195  case 2:
196  $sArticleTable = getViewName('oxarticles');
197  if ($myConfig->getConfigParam('blNewArtByInsert')) {
198  $sType = 'oxinsert';
199  } else {
200  $sType = 'oxtimestamp';
201  }
202  $sSelect = "select * from $sArticleTable ";
203  $sSelect .= "where oxparentid = '' and " . $this->getBaseObject()->getSqlActiveSnippet() . " and oxissearch = 1 order by $sType desc ";
204  if (!($iLimit = (int) $iLimit)) {
205  $iLimit = $myConfig->getConfigParam('iNrofNewcomerArticles');
206  }
207  $sSelect .= "limit " . $iLimit;
208 
209  $this->selectString($sSelect);
210  break;
211  }
212 
213  }
214 
220  public function loadTop5Articles($iLimit = null)
221  {
222  //has module?
223  $myConfig = $this->getConfig();
224 
225  if (!$myConfig->getConfigParam('bl_perfLoadPriceForAddList')) {
226  $this->getBaseObject()->disablePriceLoad();
227  }
228 
229  switch ($myConfig->getConfigParam('iTop5Mode')) {
230  case 0:
231  // switched off, do nothing
232  break;
233  case 1:
234  // manually entered
235  $this->loadActionArticles('oxtop5', $iLimit);
236  break;
237  case 2:
238  $sArticleTable = getViewName('oxarticles');
239 
240  //by default limit 5
241  $sLimit = ($iLimit > 0) ? "limit " . $iLimit : 'limit 5';
242 
243  $sSelect = "select * from $sArticleTable ";
244  $sSelect .= "where " . $this->getBaseObject()->getSqlActiveSnippet() . " and $sArticleTable.oxissearch = 1 ";
245  $sSelect .= "and $sArticleTable.oxparentid = '' and $sArticleTable.oxsoldamount>0 ";
246  $sSelect .= "order by $sArticleTable.oxsoldamount desc $sLimit";
247 
248  $this->selectString($sSelect);
249  break;
250  }
251  }
252 
261  public function loadActionArticles($sActionID, $iLimit = null)
262  {
263  // Performance
264  if (!trim($sActionID)) {
265  return;
266  }
267 
268  $sShopID = $this->getConfig()->getShopId();
269  $sActionID = oxDb::getDb()->quote(strtolower($sActionID));
270 
271  //echo $sSelect;
272  $oBaseObject = $this->getBaseObject();
273  $sArticleTable = $oBaseObject->getViewName();
274  $sArticleFields = $oBaseObject->getSelectFields();
275 
276  $oBase = oxNew("oxactions");
277  $sActiveSql = $oBase->getSqlActiveSnippet();
278  $sViewName = $oBase->getViewName();
279 
280  $sLimit = ($iLimit > 0) ? "limit " . $iLimit : '';
281 
282  $sSelect = "select $sArticleFields from oxactions2article
283  left join $sArticleTable on $sArticleTable.oxid = oxactions2article.oxartid
284  left join $sViewName on $sViewName.oxid = oxactions2article.oxactionid
285  where oxactions2article.oxshopid = '$sShopID' and oxactions2article.oxactionid = $sActionID and $sActiveSql
286  and $sArticleTable.oxid is not null and " . $oBaseObject->getSqlActiveSnippet() . "
287  order by oxactions2article.oxsort $sLimit";
288 
289  $this->selectString($sSelect);
290  }
291 
299  public function loadArticleCrossSell($sArticleId)
300  {
301  $myConfig = $this->getConfig();
302 
303  // Performance
304  if (!$myConfig->getConfigParam('bl_perfLoadCrossselling')) {
305  return null;
306  }
307 
308  $oBaseObject = $this->getBaseObject();
309  $sArticleTable = $oBaseObject->getViewName();
310 
311  $sArticleId = oxDb::getDb()->quote($sArticleId);
312 
313  $sSelect = "SELECT $sArticleTable.*
314  FROM $sArticleTable INNER JOIN oxobject2article ON oxobject2article.oxobjectid=$sArticleTable.oxid ";
315  $sSelect .= "WHERE oxobject2article.oxarticlenid = $sArticleId ";
316  $sSelect .= " AND " . $oBaseObject->getSqlActiveSnippet();
317 
318  // #525 bidirectional cross selling
319  if ($myConfig->getConfigParam('blBidirectCross')) {
320  $sSelect = "
321  (
322  SELECT $sArticleTable.* FROM $sArticleTable
323  INNER JOIN oxobject2article AS O2A1 on
324  ( O2A1.oxobjectid = $sArticleTable.oxid AND O2A1.oxarticlenid = $sArticleId )
325  WHERE 1
326  AND " . $oBaseObject->getSqlActiveSnippet() . "
327  AND ($sArticleTable.oxid != $sArticleId)
328  )
329  UNION
330  (
331  SELECT $sArticleTable.* FROM $sArticleTable
332  INNER JOIN oxobject2article AS O2A2 ON
333  ( O2A2.oxarticlenid = $sArticleTable.oxid AND O2A2.oxobjectid = $sArticleId )
334  WHERE 1
335  AND " . $oBaseObject->getSqlActiveSnippet() . "
336  AND ($sArticleTable.oxid != $sArticleId)
337  )";
338  }
339 
340  $this->setSqlLimit(0, $myConfig->getConfigParam('iNrofCrossellArticles'));
341  $this->selectString($sSelect);
342  }
343 
351  public function loadArticleAccessoires($sArticleId)
352  {
353  $myConfig = $this->getConfig();
354 
355  // Performance
356  if (!$myConfig->getConfigParam('bl_perfLoadAccessoires')) {
357  return;
358  }
359 
360  $sArticleId = oxDb::getDb()->quote($sArticleId);
361 
362  $oBaseObject = $this->getBaseObject();
363  $sArticleTable = $oBaseObject->getViewName();
364 
365  $sSelect = "select $sArticleTable.* from oxaccessoire2article left join $sArticleTable on oxaccessoire2article.oxobjectid=$sArticleTable.oxid ";
366  $sSelect .= "where oxaccessoire2article.oxarticlenid = $sArticleId ";
367  $sSelect .= " and $sArticleTable.oxid is not null and " . $oBaseObject->getSqlActiveSnippet();
368  //sorting articles
369  $sSelect .= " order by oxaccessoire2article.oxsort";
370 
371  $this->selectString($sSelect);
372  }
373 
380  public function loadCategoryIds($sCatId, $aSessionFilter)
381  {
382  $sArticleTable = $this->getBaseObject()->getViewName();
383  $sSelect = $this->_getCategorySelect($sArticleTable . '.oxid as oxid', $sCatId, $aSessionFilter);
384 
385  $this->_createIdListFromSql($sSelect);
386  }
387 
397  public function loadCategoryArticles($sCatId, $aSessionFilter, $iLimit = null)
398  {
399  $sArticleFields = $this->getBaseObject()->getSelectFields();
400 
401  $sSelect = $this->_getCategorySelect($sArticleFields, $sCatId, $aSessionFilter);
402 
403  // calc count - we can not use count($this) here as we might have paging enabled
404  // #1970C - if any filters are used, we can not use cached category article count
405  $iArticleCount = null;
406  if ($aSessionFilter) {
407  $iArticleCount = oxDb::getDb()->getOne($this->_getCategoryCountSelect($sCatId, $aSessionFilter));
408  }
409 
410  if ($iLimit = (int) $iLimit) {
411  $sSelect .= " LIMIT $iLimit";
412  }
413 
414  $this->selectString($sSelect);
415 
416  if ($iArticleCount !== null) {
417  return $iArticleCount;
418  }
419 
420  // this select is FAST so no need to hazzle here with getNrOfArticles()
421  return oxRegistry::get("oxUtilsCount")->getCatArticleCount($sCatId);
422  }
423 
432  public function loadRecommArticles($sRecommId, $sArticlesFilter = null)
433  {
434  $sSelect = $this->_getArticleSelect($sRecommId, $sArticlesFilter);
435  $this->selectString($sSelect);
436  }
437 
446  public function loadRecommArticleIds($sRecommId, $sArticlesFilter)
447  {
448  $sSelect = $this->_getArticleSelect($sRecommId, $sArticlesFilter);
449 
450  $sArtView = getViewName('oxarticles');
451  $sPartial = substr($sSelect, strpos($sSelect, ' from '));
452  $sSelect = "select distinct $sArtView.oxid $sPartial ";
453 
454  $this->_createIdListFromSql($sSelect);
455  }
456 
467  protected function _getArticleSelect($sRecommId, $sArticlesFilter = null)
468  {
469  $sRecommId = oxDb::getDb()->quote($sRecommId);
470 
471  $sArtView = getViewName('oxarticles');
472  $sSelect = "select distinct $sArtView.*, oxobject2list.oxdesc from oxobject2list ";
473  $sSelect .= "left join $sArtView on oxobject2list.oxobjectid = $sArtView.oxid ";
474  $sSelect .= "where (oxobject2list.oxlistid = $sRecommId) " . $sArticlesFilter;
475 
476  return $sSelect;
477  }
478 
487  public function loadSearchIds($sSearchStr = '', $sSearchCat = '', $sSearchVendor = '', $sSearchManufacturer = '')
488  {
489  $oDb = oxDb::getDb();
490  $sSearchCat = $sSearchCat ? $sSearchCat : null;
491  $sSearchVendor = $sSearchVendor ? $sSearchVendor : null;
492  $sSearchManufacturer = $sSearchManufacturer ? $sSearchManufacturer : null;
493 
494  $sWhere = null;
495 
496  if ($sSearchStr) {
497  $sWhere = $this->_getSearchSelect($sSearchStr);
498  }
499 
500  $sArticleTable = getViewName('oxarticles');
501 
502  // longdesc field now is kept on different table
503  $sDescTable = '';
504  $sDescJoin = '';
505  if (is_array($aSearchCols = $this->getConfig()->getConfigParam('aSearchCols'))) {
506  // @deprecated v5.3 (2016-05-04); Tags will be moved to own module.
507  if (in_array('oxlongdesc', $aSearchCols) || in_array('oxtags', $aSearchCols)) {
508  $sDescView = getViewName('oxartextends');
509  $sDescJoin = " LEFT JOIN $sDescView ON {$sDescView}.oxid={$sArticleTable}.oxid ";
510  }
511  // END deprecated
512  }
513 
514  // load the articles
515  $sSelect = "select $sArticleTable.oxid, $sArticleTable.oxtimestamp from $sArticleTable $sDescJoin where ";
516 
517  // must be additional conditions in select if searching in category
518  if ($sSearchCat) {
519  $sO2CView = getViewName('oxobject2category');
520  $sSelect = "select $sArticleTable.oxid from $sO2CView as oxobject2category, $sArticleTable $sDescJoin ";
521  $sSelect .= "where oxobject2category.oxcatnid=" . $oDb->quote($sSearchCat) . " and oxobject2category.oxobjectid=$sArticleTable.oxid and ";
522  }
523  $sSelect .= $this->getBaseObject()->getSqlActiveSnippet();
524  $sSelect .= " and $sArticleTable.oxparentid = '' and $sArticleTable.oxissearch = 1 ";
525 
526  // #671
527  if ($sSearchVendor) {
528  $sSelect .= " and $sArticleTable.oxvendorid = " . $oDb->quote($sSearchVendor) . " ";
529  }
530 
531  if ($sSearchManufacturer) {
532  $sSelect .= " and $sArticleTable.oxmanufacturerid = " . $oDb->quote($sSearchManufacturer) . " ";
533  }
534  $sSelect .= $sWhere;
535 
536  if ($this->_sCustomSorting) {
537  $sSelect .= " order by {$this->_sCustomSorting} ";
538  }
539 
540  $this->_createIdListFromSql($sSelect);
541  }
542 
549  public function loadPriceIds($dPriceFrom, $dPriceTo)
550  {
551  $sSelect = $this->_getPriceSelect($dPriceFrom, $dPriceTo);
552  $this->_createIdListFromSql($sSelect);
553  }
554 
565  public function loadPriceArticles($dPriceFrom, $dPriceTo, $oCategory = null)
566  {
567  $sSelect = $this->_getPriceSelect($dPriceFrom, $dPriceTo);
568 
569  startProfile("loadPriceArticles");
570  $this->selectString($sSelect);
571  stopProfile("loadPriceArticles");
572 
573  if (!$oCategory) {
574  return $this->count();
575  }
576 
577  return oxRegistry::get("oxUtilsCount")->getPriceCatArticleCount($oCategory->getId(), $dPriceFrom, $dPriceTo);
578  }
579 
585  public function loadVendorIDs($sVendorId)
586  {
587  $sSelect = $this->_getVendorSelect($sVendorId);
588  $this->_createIdListFromSql($sSelect);
589  }
590 
596  public function loadManufacturerIDs($sManufacturerId)
597  {
598  $sSelect = $this->_getManufacturerSelect($sManufacturerId);
599  $this->_createIdListFromSql($sSelect);
600  }
601 
611  public function loadVendorArticles($sVendorId, $oVendor = null)
612  {
613  $sSelect = $this->_getVendorSelect($sVendorId);
614  $this->selectString($sSelect);
615 
616  return oxRegistry::get("oxUtilsCount")->getVendorArticleCount($sVendorId);
617  }
618 
628  public function loadManufacturerArticles($sManufacturerId, $oManufacturer = null)
629  {
630  $sSelect = $this->_getManufacturerSelect($sManufacturerId);
631  $this->selectString($sSelect);
632 
633  return oxRegistry::get("oxUtilsCount")->getManufacturerArticleCount($sManufacturerId);
634  }
635 
646  public function loadTagArticles($sTag, $iLang)
647  {
648  $oListObject = $this->getBaseObject();
649  $sArticleTable = $oListObject->getViewName();
650  $sArticleFields = $oListObject->getSelectFields();
651  $sViewName = getViewName('oxartextends', $iLang);
652 
653  $oTag = oxNew('oxtag', $sTag);
654  $oTag->addUnderscores();
655  $sTag = $oTag->get();
656 
657  $sQ = "select {$sArticleFields} from {$sViewName} inner join {$sArticleTable} on " .
658  "{$sArticleTable}.oxid = {$sViewName}.oxid where {$sArticleTable}.oxparentid = '' AND match ( {$sViewName}.oxtags ) " .
659  "against( " . oxDb::getDb()->quote("\"" . $sTag . "\"") . " IN BOOLEAN MODE )";
660 
661  // checking stock etc
662  if (($sActiveSnippet = $oListObject->getSqlActiveSnippet())) {
663  $sQ .= " and {$sActiveSnippet}";
664  }
665 
666  if ($this->_sCustomSorting) {
667  $sSort = $this->_sCustomSorting;
668  if (strpos($sSort, '.') === false) {
669  $sSort = $sArticleTable . '.' . $sSort;
670  }
671  $sQ .= " order by $sSort ";
672  }
673 
674  $this->selectString($sQ);
675 
676  // calc count - we can not use count($this) here as we might have paging enabled
677  return oxRegistry::get("oxUtilsCount")->getTagArticleCount($sTag, $iLang);
678  }
679 
690  public function getTagArticleIds($sTag, $iLang)
691  {
692  $oListObject = $this->getBaseObject();
693  $sArticleTable = $oListObject->getViewName();
694  $sViewName = getViewName('oxartextends', $iLang);
695 
696  $oTag = oxNew('oxtag', $sTag);
697  $oTag->addUnderscores();
698  $sTag = $oTag->get();
699 
700  $sQ = "select {$sViewName}.oxid from {$sViewName} inner join {$sArticleTable} on " .
701  "{$sArticleTable}.oxid = {$sViewName}.oxid where {$sArticleTable}.oxparentid = '' and {$sArticleTable}.oxissearch = 1 and " .
702  "match ( {$sViewName}.oxtags ) " .
703  "against( " . oxDb::getDb()->quote("\"" . $sTag . "\"") . " IN BOOLEAN MODE )";
704 
705  // checking stock etc
706  if (($sActiveSnippet = $oListObject->getSqlActiveSnippet())) {
707  $sQ .= " and {$sActiveSnippet}";
708  }
709 
710  if ($this->_sCustomSorting) {
711  $sSort = $this->_sCustomSorting;
712  if (strpos($sSort, '.') === false) {
713  $sSort = $sArticleTable . '.' . $sSort;
714  }
715  $sQ .= " order by $sSort ";
716  }
717 
718  return $this->_createIdListFromSql($sQ);
719  }
720 
728  public function loadIds($aIds)
729  {
730  if (!count($aIds)) {
731  $this->clear();
732 
733  return;
734  }
735 
736  foreach ($aIds as $iKey => $sVal) {
737  $aIds[$iKey] = oxDb::getInstance()->escapeString($sVal);
738  }
739 
740  $oBaseObject = $this->getBaseObject();
741  $sArticleTable = $oBaseObject->getViewName();
742  $sArticleFields = $oBaseObject->getSelectFields();
743 
744  $sSelect = "select $sArticleFields from $sArticleTable ";
745  $sSelect .= "where $sArticleTable.oxid in ( '" . implode("','", $aIds) . "' ) and ";
746  $sSelect .= $oBaseObject->getSqlActiveSnippet();
747 
748  $this->selectString($sSelect);
749  }
750 
758  public function loadOrderArticles($aOrders)
759  {
760  if (!count($aOrders)) {
761  $this->clear();
762 
763  return;
764  }
765 
766  foreach ($aOrders as $iKey => $oOrder) {
767  $aOrdersIds[] = $oOrder->getId();
768  }
769 
770  $oBaseObject = $this->getBaseObject();
771  $sArticleTable = $oBaseObject->getViewName();
772  $sArticleFields = $oBaseObject->getSelectFields();
773  $sArticleFields = str_replace("`$sArticleTable`.`oxid`", "`oxorderarticles`.`oxartid` AS `oxid`", $sArticleFields);
774 
775  $sSelect = "SELECT $sArticleFields FROM oxorderarticles ";
776  $sSelect .= "left join $sArticleTable on oxorderarticles.oxartid = $sArticleTable.oxid ";
777  $sSelect .= "WHERE oxorderarticles.oxorderid IN ( '" . implode("','", $aOrdersIds) . "' ) ";
778  $sSelect .= "order by $sArticleTable.oxid ";
779 
780  $this->selectString($sSelect);
781 
782  // not active or not available products must not have button "tobasket"
783  $sNow = date('Y-m-d H:i:s');
784  foreach ($this as $oArticle) {
785  if (!$oArticle->oxarticles__oxactive->value &&
786  ($oArticle->oxarticles__oxactivefrom->value > $sNow ||
787  $oArticle->oxarticles__oxactiveto->value < $sNow
788  )
789  ) {
790  $oArticle->setBuyableState(false);
791  }
792  }
793  }
794 
800  public function loadStockRemindProducts($aBasketContents)
801  {
802  if (is_array($aBasketContents) && count($aBasketContents)) {
803  $oDb = oxDb::getDb();
804  foreach ($aBasketContents as $oBasketItem) {
805  $aArtIds[] = $oDb->quote($oBasketItem->getProductId());
806  }
807 
808  $oBaseObject = $this->getBaseObject();
809 
810  $sFieldNames = $oBaseObject->getSelectFields();
811  $sTable = $oBaseObject->getViewName();
812 
813  // fetching actual db stock state and reminder status
814  $sQ = "select {$sFieldNames} from {$sTable} where {$sTable}.oxid in ( " . implode(",", $aArtIds) . " ) and
815  oxremindactive = '1' and oxstock <= oxremindamount";
816  $this->selectString($sQ);
817 
818  // updating stock reminder state
819  if ($this->count()) {
820  $sQ = "update {$sTable} set oxremindactive = '2' where {$sTable}.oxid in ( " . implode(",", $aArtIds) . " ) and
821  oxremindactive = '1' and oxstock <= oxremindamount";
822  $oDb->execute($sQ);
823  }
824  }
825  }
826 
832  public function renewPriceUpdateTime()
833  {
834  $oDb = oxDb::getDb();
835 
836  // fetching next update time
837  $sQ = "select unix_timestamp( oxupdatepricetime ) from %s where oxupdatepricetime > 0 order by oxupdatepricetime asc";
838  $iTimeToUpdate = $oDb->getOne(sprintf($sQ, "`oxarticles`"), false, false);
839 
840 
841  // next day?
842  $iCurrUpdateTime = oxRegistry::get("oxUtilsDate")->getTime();
843  $iNextUpdateTime = $iCurrUpdateTime + 3600 * 24;
844 
845  // renew next update time
846  if (!$iTimeToUpdate || $iTimeToUpdate > $iNextUpdateTime) {
847  $iTimeToUpdate = $iNextUpdateTime;
848  }
849 
850  $this->getConfig()->saveShopConfVar("num", "iTimeToUpdatePrices", $iTimeToUpdate);
851 
852  return $iTimeToUpdate;
853  }
854 
863  public function updateUpcomingPrices($blForceUpdate = false)
864  {
865  $blUpdated = false;
866 
867  if ($blForceUpdate || $this->_canUpdatePrices()) {
868 
869  $oDb = oxDb::getDb();
870 
871  $oDb->startTransaction();
872 
873  $sCurrUpdateTime = date("Y-m-d H:i:s", oxRegistry::get("oxUtilsDate")->getTime());
874 
875  // Collect article id's for later recalculation.
876  $sQ = "SELECT `oxid` FROM `oxarticles`
877  WHERE `oxupdatepricetime` > 0 AND `oxupdatepricetime` <= '{$sCurrUpdateTime}'";
878  $aUpdatedArticleIds = $oDb->getCol($sQ, false, false);
879 
880  // updating oxarticles
881  $sQ = "UPDATE %s SET
882  `oxprice` = IF( `oxupdateprice` > 0, `oxupdateprice`, `oxprice` ),
883  `oxpricea` = IF( `oxupdatepricea` > 0, `oxupdatepricea`, `oxpricea` ),
884  `oxpriceb` = IF( `oxupdatepriceb` > 0, `oxupdatepriceb`, `oxpriceb` ),
885  `oxpricec` = IF( `oxupdatepricec` > 0, `oxupdatepricec`, `oxpricec` ),
886  `oxupdatepricetime` = 0,
887  `oxupdateprice` = 0,
888  `oxupdatepricea` = 0,
889  `oxupdatepriceb` = 0,
890  `oxupdatepricec` = 0
891  WHERE
892  `oxupdatepricetime` > 0 AND
893  `oxupdatepricetime` <= '{$sCurrUpdateTime}'";
894  $blUpdated = $oDb->execute(sprintf($sQ, "`oxarticles`"));
895 
896 
897  // renew update time in case update is not forced
898  if (!$blForceUpdate) {
899  $this->renewPriceUpdateTime();
900  }
901 
902  $oDb->commitTransaction();
903 
904  // recalculate oxvarminprice and oxvarmaxprice for parent
905  if (is_array($aUpdatedArticleIds)) {
906  foreach ($aUpdatedArticleIds as $sArticleId) {
907  $oArticle = oxNew('oxarticle');
908  $oArticle->load($sArticleId);
909  $oArticle->onChange();
910  }
911  }
912 
913  }
914 
915  return $blUpdated;
916  }
917 
923  protected function _createIdListFromSql($sSql)
924  {
925  $rs = oxDb::getDb(oxDb::FETCH_MODE_ASSOC)->select($sSql);
926  if ($rs != false && $rs->recordCount() > 0) {
927  while (!$rs->EOF) {
928  $rs->fields = array_change_key_case($rs->fields, CASE_LOWER);
929  $this[$rs->fields['oxid']] = $rs->fields['oxid']; //only the oxid
930  $rs->moveNext();
931  }
932  }
933  }
934 
943  protected function _getFilterIdsSql($sCatId, $aFilter)
944  {
945  $sO2CView = getViewName('oxobject2category');
946  $sO2AView = getViewName('oxobject2attribute');
947 
948  $sFilter = '';
949  $iCnt = 0;
950 
951  $oDb = oxDb::getDb();
952  foreach ($aFilter as $sAttrId => $sValue) {
953  if ($sValue) {
954  if ($sFilter) {
955  $sFilter .= ' or ';
956  }
957  $sValue = $oDb->quote($sValue);
958  $sAttrId = $oDb->quote($sAttrId);
959 
960  $sFilter .= "( oa.oxattrid = {$sAttrId} and oa.oxvalue = {$sValue} )";
961  $iCnt++;
962  }
963  }
964  if ($sFilter) {
965  $sFilter = "WHERE $sFilter ";
966  }
967 
968  $sFilterSelect = "select oc.oxobjectid as oxobjectid, count(*) as cnt from ";
969  $sFilterSelect .= "(SELECT * FROM $sO2CView WHERE $sO2CView.oxcatnid = '$sCatId' GROUP BY $sO2CView.oxobjectid, $sO2CView.oxcatnid) as oc ";
970  $sFilterSelect .= "INNER JOIN $sO2AView as oa ON ( oa.oxobjectid = oc.oxobjectid ) ";
971 
972  return $sFilterSelect . "{$sFilter} GROUP BY oa.oxobjectid HAVING cnt = $iCnt ";
973  }
974 
983  protected function _getFilterSql($sCatId, $aFilter)
984  {
985  $sArticleTable = getViewName('oxarticles');
986  $aIds = oxDb::getDb(oxDb::FETCH_MODE_ASSOC)->getAll($this->_getFilterIdsSql($sCatId, $aFilter));
987  $sIds = '';
988 
989  if ($aIds) {
990  foreach ($aIds as $aArt) {
991  if ($sIds) {
992  $sIds .= ', ';
993  }
994  $sIds .= oxDb::getDb()->quote(current($aArt));
995  }
996 
997  if ($sIds) {
998  $sFilterSql = " and $sArticleTable.oxid in ( $sIds ) ";
999  }
1000  // bug fix #0001695: if no articles found return false
1001  } elseif (!(current($aFilter) == '' && count(array_unique($aFilter)) == 1)) {
1002  $sFilterSql = " and false ";
1003  }
1004 
1005  return $sFilterSql;
1006  }
1007 
1017  protected function _getCategorySelect($sFields, $sCatId, $aSessionFilter)
1018  {
1019  $sArticleTable = getViewName('oxarticles');
1020  $sO2CView = getViewName('oxobject2category');
1021 
1022  // ----------------------------------
1023  // sorting
1024  $sSorting = '';
1025  if ($this->_sCustomSorting) {
1026  $sSorting = " {$this->_sCustomSorting} , ";
1027  }
1028 
1029  // ----------------------------------
1030  // filtering ?
1031  $sFilterSql = '';
1032  $iLang = oxRegistry::getLang()->getBaseLanguage();
1033  if ($aSessionFilter && isset($aSessionFilter[$sCatId][$iLang])) {
1034  $sFilterSql = $this->_getFilterSql($sCatId, $aSessionFilter[$sCatId][$iLang]);
1035  }
1036 
1037  $oDb = oxDb::getDb();
1038 
1039  $sSelect = "SELECT $sFields, $sArticleTable.oxtimestamp FROM $sO2CView as oc left join $sArticleTable
1040  ON $sArticleTable.oxid = oc.oxobjectid
1041  WHERE " . $this->getBaseObject()->getSqlActiveSnippet() . " and $sArticleTable.oxparentid = ''
1042  and oc.oxcatnid = " . $oDb->quote($sCatId) . " $sFilterSql ORDER BY $sSorting oc.oxpos, oc.oxobjectid ";
1043 
1044  return $sSelect;
1045  }
1046 
1055  protected function _getCategoryCountSelect($sCatId, $aSessionFilter)
1056  {
1057  $sArticleTable = getViewName('oxarticles');
1058  $sO2CView = getViewName('oxobject2category');
1059 
1060 
1061  // ----------------------------------
1062  // filtering ?
1063  $sFilterSql = '';
1064  $iLang = oxRegistry::getLang()->getBaseLanguage();
1065  if ($aSessionFilter && isset($aSessionFilter[$sCatId][$iLang])) {
1066  $sFilterSql = $this->_getFilterSql($sCatId, $aSessionFilter[$sCatId][$iLang]);
1067  }
1068 
1069  $oDb = oxDb::getDb();
1070 
1071  $sSelect = "SELECT COUNT(*) FROM $sO2CView as oc left join $sArticleTable
1072  ON $sArticleTable.oxid = oc.oxobjectid
1073  WHERE " . $this->getBaseObject()->getSqlActiveSnippet() . " and $sArticleTable.oxparentid = ''
1074  and oc.oxcatnid = " . $oDb->quote($sCatId) . " $sFilterSql ";
1075 
1076  return $sSelect;
1077  }
1078 
1086  protected function _getSearchSelect($sSearchString)
1087  {
1088  // check if it has string at all
1089  if (!$sSearchString || !str_replace(' ', '', $sSearchString)) {
1090  return '';
1091  }
1092 
1093  $oDb = oxDb::getDb();
1094  $myConfig = $this->getConfig();
1095  $myUtils = oxRegistry::getUtils();
1096  $sArticleTable = $this->getBaseObject()->getViewName();
1097 
1098  $aSearch = explode(' ', $sSearchString);
1099 
1100  $sSearch = ' and ( ';
1101  $blSep = false;
1102 
1103  // #723
1104  if ($myConfig->getConfigParam('blSearchUseAND')) {
1105  $sSearchSep = ' and ';
1106  } else {
1107  $sSearchSep = ' or ';
1108  }
1109 
1110  $aSearchCols = $myConfig->getConfigParam('aSearchCols');
1111  $oBaseObject = $this->getBaseObject();
1112  $myUtilsString = oxRegistry::get("oxUtilsString");
1113  foreach ($aSearch as $sSearchString) {
1114 
1115  if (!strlen($sSearchString)) {
1116  continue;
1117  }
1118 
1119  if ($blSep) {
1120  $sSearch .= $sSearchSep;
1121  }
1122  $blSep2 = false;
1123  $sSearch .= '( ';
1124 
1125  $sUml = $myUtilsString->prepareStrForSearch($sSearchString);
1126  foreach ($aSearchCols as $sField) {
1127 
1128  if ($blSep2) {
1129  $sSearch .= ' or ';
1130  }
1131 
1132  // @deprecated v5.3 (2016-05-04); Tags will be moved to own module.
1133  // as long description now is on different table table must differ
1134  if ($sField == 'oxlongdesc' || $sField == 'oxtags') {
1135  $sSearchTable = getViewName('oxartextends');
1136  } else {
1137  $sSearchTable = $sArticleTable;
1138  }
1139  // END deprecated
1140 
1141  $sSearch .= $sSearchTable . '.' . $sField . ' like ' . $oDb->quote('%' . $sSearchString . '%') . ' ';
1142  if ($sUml) {
1143  $sSearch .= ' or ' . $sSearchTable . '.' . $sField . ' like ' . $oDb->quote('%' . $sUml . '%');
1144  }
1145  $blSep2 = true;
1146  }
1147  $sSearch .= ' ) ';
1148  $blSep = true;
1149  }
1150  $sSearch .= ' ) ';
1151 
1152  return $sSearch;
1153  }
1154 
1163  protected function _getPriceSelect($dPriceFrom, $dPriceTo)
1164  {
1165  $oBaseObject = $this->getBaseObject();
1166  $sArticleTable = $oBaseObject->getViewName();
1167  $sSelectFields = $oBaseObject->getSelectFields();
1168 
1169  $sSubSelect = "";
1170 
1171  $sSelect = "select {$sSelectFields} from {$sArticleTable} where oxvarminprice >= 0 ";
1172  $sSelect .= $dPriceTo ? "and oxvarminprice <= " . (double) $dPriceTo . " " : " ";
1173  $sSelect .= $dPriceFrom ? "and oxvarminprice >= " . (double) $dPriceFrom . " " : " ";
1174 
1175  $sSelect .= " and " . $oBaseObject->getSqlActiveSnippet() . " and {$sArticleTable}.oxissearch = 1";
1176 
1177  if (!$this->_sCustomSorting) {
1178  $sSelect .= " order by {$sArticleTable}.oxvarminprice asc , {$sArticleTable}.oxid";
1179  } else {
1180  $sSelect .= " order by {$this->_sCustomSorting}, {$sArticleTable}.oxid ";
1181  }
1182 
1183  return $sSelect;
1184  }
1185 
1193  protected function _getVendorSelect($sVendorId)
1194  {
1195  $sArticleTable = getViewName('oxarticles');
1196  $oBaseObject = $this->getBaseObject();
1197  $sFieldNames = $oBaseObject->getSelectFields();
1198  $sSelect = "select $sFieldNames from $sArticleTable ";
1199  $sSelect .= "where $sArticleTable.oxvendorid = " . oxDb::getDb()->quote($sVendorId) . " ";
1200  $sSelect .= " and " . $oBaseObject->getSqlActiveSnippet() . " and $sArticleTable.oxparentid = '' ";
1201 
1202  if ($this->_sCustomSorting) {
1203  $sSelect .= " ORDER BY {$this->_sCustomSorting} ";
1204  }
1205 
1206  return $sSelect;
1207  }
1208 
1216  protected function _getManufacturerSelect($sManufacturerId)
1217  {
1218  $sArticleTable = getViewName('oxarticles');
1219  $oBaseObject = $this->getBaseObject();
1220  $sFieldNames = $oBaseObject->getSelectFields();
1221  $sSelect = "select $sFieldNames from $sArticleTable ";
1222  $sSelect .= "where $sArticleTable.oxmanufacturerid = " . oxDb::getDb()->quote($sManufacturerId) . " ";
1223  $sSelect .= " and " . $oBaseObject->getSqlActiveSnippet() . " and $sArticleTable.oxparentid = '' ";
1224 
1225  if ($this->_sCustomSorting) {
1226  $sSelect .= " ORDER BY {$this->_sCustomSorting} ";
1227  }
1228 
1229  return $sSelect;
1230  }
1231 
1237  protected function _canUpdatePrices()
1238  {
1239  $oConfig = $this->getConfig();
1240  $blCan = false;
1241 
1242  // crontab is off?
1243  if (!$oConfig->getConfigParam("blUseCron")) {
1244  $iTimeToUpdate = $oConfig->getConfigParam("iTimeToUpdatePrices");
1245  if (!$iTimeToUpdate || $iTimeToUpdate <= oxRegistry::get("oxUtilsDate")->getTime()) {
1246  $blCan = true;
1247  }
1248  }
1249 
1250  return $blCan;
1251  }
1252 }