OXID eShop CE  4.9.7
 All Classes 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 
430  public function loadRecommArticles($sRecommId, $sArticlesFilter = null)
431  {
432  $sSelect = $this->_getArticleSelect($sRecommId, $sArticlesFilter);
433  $this->selectString($sSelect);
434  }
435 
442  public function loadRecommArticleIds($sRecommId, $sArticlesFilter)
443  {
444  $sSelect = $this->_getArticleSelect($sRecommId, $sArticlesFilter);
445 
446  $sArtView = getViewName('oxarticles');
447  $sPartial = substr($sSelect, strpos($sSelect, ' from '));
448  $sSelect = "select distinct $sArtView.oxid $sPartial ";
449 
450  $this->_createIdListFromSql($sSelect);
451  }
452 
461  protected function _getArticleSelect($sRecommId, $sArticlesFilter = null)
462  {
463  $sRecommId = oxDb::getDb()->quote($sRecommId);
464 
465  $sArtView = getViewName('oxarticles');
466  $sSelect = "select distinct $sArtView.*, oxobject2list.oxdesc from oxobject2list ";
467  $sSelect .= "left join $sArtView on oxobject2list.oxobjectid = $sArtView.oxid ";
468  $sSelect .= "where (oxobject2list.oxlistid = $sRecommId) " . $sArticlesFilter;
469 
470  return $sSelect;
471  }
472 
481  public function loadSearchIds($sSearchStr = '', $sSearchCat = '', $sSearchVendor = '', $sSearchManufacturer = '')
482  {
483  $oDb = oxDb::getDb();
484  $sSearchCat = $sSearchCat ? $sSearchCat : null;
485  $sSearchVendor = $sSearchVendor ? $sSearchVendor : null;
486  $sSearchManufacturer = $sSearchManufacturer ? $sSearchManufacturer : null;
487 
488  $sWhere = null;
489 
490  if ($sSearchStr) {
491  $sWhere = $this->_getSearchSelect($sSearchStr);
492  }
493 
494  $sArticleTable = getViewName('oxarticles');
495 
496  // longdesc field now is kept on different table
497  $sDescTable = '';
498  $sDescJoin = '';
499  if (is_array($aSearchCols = $this->getConfig()->getConfigParam('aSearchCols'))) {
500  if (in_array('oxlongdesc', $aSearchCols) || in_array('oxtags', $aSearchCols)) {
501  $sDescView = getViewName('oxartextends');
502  $sDescJoin = " LEFT JOIN $sDescView ON {$sDescView}.oxid={$sArticleTable}.oxid ";
503  }
504  }
505 
506  // load the articles
507  $sSelect = "select $sArticleTable.oxid, $sArticleTable.oxtimestamp from $sArticleTable $sDescJoin where ";
508 
509  // must be additional conditions in select if searching in category
510  if ($sSearchCat) {
511  $sO2CView = getViewName('oxobject2category');
512  $sSelect = "select $sArticleTable.oxid from $sO2CView as oxobject2category, $sArticleTable $sDescJoin ";
513  $sSelect .= "where oxobject2category.oxcatnid=" . $oDb->quote($sSearchCat) . " and oxobject2category.oxobjectid=$sArticleTable.oxid and ";
514  }
515  $sSelect .= $this->getBaseObject()->getSqlActiveSnippet();
516  $sSelect .= " and $sArticleTable.oxparentid = '' and $sArticleTable.oxissearch = 1 ";
517 
518  // #671
519  if ($sSearchVendor) {
520  $sSelect .= " and $sArticleTable.oxvendorid = " . $oDb->quote($sSearchVendor) . " ";
521  }
522 
523  if ($sSearchManufacturer) {
524  $sSelect .= " and $sArticleTable.oxmanufacturerid = " . $oDb->quote($sSearchManufacturer) . " ";
525  }
526  $sSelect .= $sWhere;
527 
528  if ($this->_sCustomSorting) {
529  $sSelect .= " order by {$this->_sCustomSorting} ";
530  }
531 
532  $this->_createIdListFromSql($sSelect);
533  }
534 
541  public function loadPriceIds($dPriceFrom, $dPriceTo)
542  {
543  $sSelect = $this->_getPriceSelect($dPriceFrom, $dPriceTo);
544  $this->_createIdListFromSql($sSelect);
545  }
546 
557  public function loadPriceArticles($dPriceFrom, $dPriceTo, $oCategory = null)
558  {
559  $sSelect = $this->_getPriceSelect($dPriceFrom, $dPriceTo);
560 
561  startProfile("loadPriceArticles");
562  $this->selectString($sSelect);
563  stopProfile("loadPriceArticles");
564 
565  if (!$oCategory) {
566  return $this->count();
567  }
568 
569  return oxRegistry::get("oxUtilsCount")->getPriceCatArticleCount($oCategory->getId(), $dPriceFrom, $dPriceTo);
570  }
571 
577  public function loadVendorIDs($sVendorId)
578  {
579  $sSelect = $this->_getVendorSelect($sVendorId);
580  $this->_createIdListFromSql($sSelect);
581  }
582 
588  public function loadManufacturerIDs($sManufacturerId)
589  {
590  $sSelect = $this->_getManufacturerSelect($sManufacturerId);
591  $this->_createIdListFromSql($sSelect);
592  }
593 
603  public function loadVendorArticles($sVendorId, $oVendor = null)
604  {
605  $sSelect = $this->_getVendorSelect($sVendorId);
606  $this->selectString($sSelect);
607 
608  return oxRegistry::get("oxUtilsCount")->getVendorArticleCount($sVendorId);
609  }
610 
620  public function loadManufacturerArticles($sManufacturerId, $oManufacturer = null)
621  {
622  $sSelect = $this->_getManufacturerSelect($sManufacturerId);
623  $this->selectString($sSelect);
624 
625  return oxRegistry::get("oxUtilsCount")->getManufacturerArticleCount($sManufacturerId);
626  }
627 
636  public function loadTagArticles($sTag, $iLang)
637  {
638  $oListObject = $this->getBaseObject();
639  $sArticleTable = $oListObject->getViewName();
640  $sArticleFields = $oListObject->getSelectFields();
641  $sViewName = getViewName('oxartextends', $iLang);
642 
643  $oTag = oxNew('oxtag', $sTag);
644  $oTag->addUnderscores();
645  $sTag = $oTag->get();
646 
647  $sQ = "select {$sArticleFields} from {$sViewName} inner join {$sArticleTable} on " .
648  "{$sArticleTable}.oxid = {$sViewName}.oxid where {$sArticleTable}.oxparentid = '' AND match ( {$sViewName}.oxtags ) " .
649  "against( " . oxDb::getDb()->quote("\"" . $sTag . "\"") . " IN BOOLEAN MODE )";
650 
651  // checking stock etc
652  if (($sActiveSnippet = $oListObject->getSqlActiveSnippet())) {
653  $sQ .= " and {$sActiveSnippet}";
654  }
655 
656  if ($this->_sCustomSorting) {
657  $sSort = $this->_sCustomSorting;
658  if (strpos($sSort, '.') === false) {
659  $sSort = $sArticleTable . '.' . $sSort;
660  }
661  $sQ .= " order by $sSort ";
662  }
663 
664  $this->selectString($sQ);
665 
666  // calc count - we can not use count($this) here as we might have paging enabled
667  return oxRegistry::get("oxUtilsCount")->getTagArticleCount($sTag, $iLang);
668  }
669 
678  public function getTagArticleIds($sTag, $iLang)
679  {
680  $oListObject = $this->getBaseObject();
681  $sArticleTable = $oListObject->getViewName();
682  $sViewName = getViewName('oxartextends', $iLang);
683 
684  $oTag = oxNew('oxtag', $sTag);
685  $oTag->addUnderscores();
686  $sTag = $oTag->get();
687 
688  $sQ = "select {$sViewName}.oxid from {$sViewName} inner join {$sArticleTable} on " .
689  "{$sArticleTable}.oxid = {$sViewName}.oxid where {$sArticleTable}.oxparentid = '' and {$sArticleTable}.oxissearch = 1 and " .
690  "match ( {$sViewName}.oxtags ) " .
691  "against( " . oxDb::getDb()->quote("\"" . $sTag . "\"") . " IN BOOLEAN MODE )";
692 
693  // checking stock etc
694  if (($sActiveSnippet = $oListObject->getSqlActiveSnippet())) {
695  $sQ .= " and {$sActiveSnippet}";
696  }
697 
698  if ($this->_sCustomSorting) {
699  $sSort = $this->_sCustomSorting;
700  if (strpos($sSort, '.') === false) {
701  $sSort = $sArticleTable . '.' . $sSort;
702  }
703  $sQ .= " order by $sSort ";
704  }
705 
706  return $this->_createIdListFromSql($sQ);
707  }
708 
716  public function loadIds($aIds)
717  {
718  if (!count($aIds)) {
719  $this->clear();
720 
721  return;
722  }
723 
724  foreach ($aIds as $iKey => $sVal) {
725  $aIds[$iKey] = oxDb::getInstance()->escapeString($sVal);
726  }
727 
728  $oBaseObject = $this->getBaseObject();
729  $sArticleTable = $oBaseObject->getViewName();
730  $sArticleFields = $oBaseObject->getSelectFields();
731 
732  $sSelect = "select $sArticleFields from $sArticleTable ";
733  $sSelect .= "where $sArticleTable.oxid in ( '" . implode("','", $aIds) . "' ) and ";
734  $sSelect .= $oBaseObject->getSqlActiveSnippet();
735 
736  $this->selectString($sSelect);
737  }
738 
746  public function loadOrderArticles($aOrders)
747  {
748  if (!count($aOrders)) {
749  $this->clear();
750 
751  return;
752  }
753 
754  foreach ($aOrders as $iKey => $oOrder) {
755  $aOrdersIds[] = $oOrder->getId();
756  }
757 
758  $oBaseObject = $this->getBaseObject();
759  $sArticleTable = $oBaseObject->getViewName();
760  $sArticleFields = $oBaseObject->getSelectFields();
761  $sArticleFields = str_replace("`$sArticleTable`.`oxid`", "`oxorderarticles`.`oxartid` AS `oxid`", $sArticleFields);
762 
763  $sSelect = "SELECT $sArticleFields FROM oxorderarticles ";
764  $sSelect .= "left join $sArticleTable on oxorderarticles.oxartid = $sArticleTable.oxid ";
765  $sSelect .= "WHERE oxorderarticles.oxorderid IN ( '" . implode("','", $aOrdersIds) . "' ) ";
766  $sSelect .= "order by $sArticleTable.oxid ";
767 
768  $this->selectString($sSelect);
769 
770  // not active or not available products must not have button "tobasket"
771  $sNow = date('Y-m-d H:i:s');
772  foreach ($this as $oArticle) {
773  if (!$oArticle->oxarticles__oxactive->value &&
774  ($oArticle->oxarticles__oxactivefrom->value > $sNow ||
775  $oArticle->oxarticles__oxactiveto->value < $sNow
776  )
777  ) {
778  $oArticle->setBuyableState(false);
779  }
780  }
781  }
782 
788  public function loadStockRemindProducts($aBasketContents)
789  {
790  if (is_array($aBasketContents) && count($aBasketContents)) {
791  $oDb = oxDb::getDb();
792  foreach ($aBasketContents as $oBasketItem) {
793  $aArtIds[] = $oDb->quote($oBasketItem->getProductId());
794  }
795 
796  $oBaseObject = $this->getBaseObject();
797 
798  $sFieldNames = $oBaseObject->getSelectFields();
799  $sTable = $oBaseObject->getViewName();
800 
801  // fetching actual db stock state and reminder status
802  $sQ = "select {$sFieldNames} from {$sTable} where {$sTable}.oxid in ( " . implode(",", $aArtIds) . " ) and
803  oxremindactive = '1' and oxstock <= oxremindamount";
804  $this->selectString($sQ);
805 
806  // updating stock reminder state
807  if ($this->count()) {
808  $sQ = "update {$sTable} set oxremindactive = '2' where {$sTable}.oxid in ( " . implode(",", $aArtIds) . " ) and
809  oxremindactive = '1' and oxstock <= oxremindamount";
810  $oDb->execute($sQ);
811  }
812  }
813  }
814 
820  public function renewPriceUpdateTime()
821  {
822  $oDb = oxDb::getDb();
823 
824  // fetching next update time
825  $sQ = "select unix_timestamp( oxupdatepricetime ) from %s where oxupdatepricetime > 0 order by oxupdatepricetime asc";
826  $iTimeToUpdate = $oDb->getOne(sprintf($sQ, "`oxarticles`"), false, false);
827 
828 
829  // next day?
830  $iCurrUpdateTime = oxRegistry::get("oxUtilsDate")->getTime();
831  $iNextUpdateTime = $iCurrUpdateTime + 3600 * 24;
832 
833  // renew next update time
834  if (!$iTimeToUpdate || $iTimeToUpdate > $iNextUpdateTime) {
835  $iTimeToUpdate = $iNextUpdateTime;
836  }
837 
838  $this->getConfig()->saveShopConfVar("num", "iTimeToUpdatePrices", $iTimeToUpdate);
839 
840  return $iTimeToUpdate;
841  }
842 
851  public function updateUpcomingPrices($blForceUpdate = false)
852  {
853  $blUpdated = false;
854 
855  if ($blForceUpdate || $this->_canUpdatePrices()) {
856 
857  $oDb = oxDb::getDb();
858 
859  $oDb->startTransaction();
860 
861  $sCurrUpdateTime = date("Y-m-d H:i:s", oxRegistry::get("oxUtilsDate")->getTime());
862 
863  // Collect article id's for later recalculation.
864  $sQ = "SELECT `oxid` FROM `oxarticles`
865  WHERE `oxupdatepricetime` > 0 AND `oxupdatepricetime` <= '{$sCurrUpdateTime}'";
866  $aUpdatedArticleIds = $oDb->getCol($sQ, false, false);
867 
868  // updating oxarticles
869  $sQ = "UPDATE %s SET
870  `oxprice` = IF( `oxupdateprice` > 0, `oxupdateprice`, `oxprice` ),
871  `oxpricea` = IF( `oxupdatepricea` > 0, `oxupdatepricea`, `oxpricea` ),
872  `oxpriceb` = IF( `oxupdatepriceb` > 0, `oxupdatepriceb`, `oxpriceb` ),
873  `oxpricec` = IF( `oxupdatepricec` > 0, `oxupdatepricec`, `oxpricec` ),
874  `oxupdatepricetime` = 0,
875  `oxupdateprice` = 0,
876  `oxupdatepricea` = 0,
877  `oxupdatepriceb` = 0,
878  `oxupdatepricec` = 0
879  WHERE
880  `oxupdatepricetime` > 0 AND
881  `oxupdatepricetime` <= '{$sCurrUpdateTime}'";
882  $blUpdated = $oDb->execute(sprintf($sQ, "`oxarticles`"));
883 
884 
885  // renew update time in case update is not forced
886  if (!$blForceUpdate) {
887  $this->renewPriceUpdateTime();
888  }
889 
890  $oDb->commitTransaction();
891 
892  // recalculate oxvarminprice and oxvarmaxprice for parent
893  if (is_array($aUpdatedArticleIds)) {
894  foreach ($aUpdatedArticleIds as $sArticleId) {
895  $oArticle = oxNew('oxarticle');
896  $oArticle->load($sArticleId);
897  $oArticle->onChange();
898  }
899  }
900 
901  }
902 
903  return $blUpdated;
904  }
905 
911  protected function _createIdListFromSql($sSql)
912  {
913  $rs = oxDb::getDb(oxDb::FETCH_MODE_ASSOC)->select($sSql);
914  if ($rs != false && $rs->recordCount() > 0) {
915  while (!$rs->EOF) {
916  $rs->fields = array_change_key_case($rs->fields, CASE_LOWER);
917  $this[$rs->fields['oxid']] = $rs->fields['oxid']; //only the oxid
918  $rs->moveNext();
919  }
920  }
921  }
922 
931  protected function _getFilterIdsSql($sCatId, $aFilter)
932  {
933  $sO2CView = getViewName('oxobject2category');
934  $sO2AView = getViewName('oxobject2attribute');
935 
936  $sFilter = '';
937  $iCnt = 0;
938 
939  $oDb = oxDb::getDb();
940  foreach ($aFilter as $sAttrId => $sValue) {
941  if ($sValue) {
942  if ($sFilter) {
943  $sFilter .= ' or ';
944  }
945  $sValue = $oDb->quote($sValue);
946  $sAttrId = $oDb->quote($sAttrId);
947 
948  $sFilter .= "( oa.oxattrid = {$sAttrId} and oa.oxvalue = {$sValue} )";
949  $iCnt++;
950  }
951  }
952  if ($sFilter) {
953  $sFilter = "WHERE $sFilter ";
954  }
955 
956  $sFilterSelect = "select oc.oxobjectid as oxobjectid, count(*) as cnt from ";
957  $sFilterSelect .= "(SELECT * FROM $sO2CView WHERE $sO2CView.oxcatnid = '$sCatId' GROUP BY $sO2CView.oxobjectid, $sO2CView.oxcatnid) as oc ";
958  $sFilterSelect .= "INNER JOIN $sO2AView as oa ON ( oa.oxobjectid = oc.oxobjectid ) ";
959 
960  return $sFilterSelect . "{$sFilter} GROUP BY oa.oxobjectid HAVING cnt = $iCnt ";
961  }
962 
971  protected function _getFilterSql($sCatId, $aFilter)
972  {
973  $sArticleTable = getViewName('oxarticles');
974  $aIds = oxDb::getDb(oxDb::FETCH_MODE_ASSOC)->getAll($this->_getFilterIdsSql($sCatId, $aFilter));
975  $sIds = '';
976 
977  if ($aIds) {
978  foreach ($aIds as $aArt) {
979  if ($sIds) {
980  $sIds .= ', ';
981  }
982  $sIds .= oxDb::getDb()->quote(current($aArt));
983  }
984 
985  if ($sIds) {
986  $sFilterSql = " and $sArticleTable.oxid in ( $sIds ) ";
987  }
988  // bug fix #0001695: if no articles found return false
989  } elseif (!(current($aFilter) == '' && count(array_unique($aFilter)) == 1)) {
990  $sFilterSql = " and false ";
991  }
992 
993  return $sFilterSql;
994  }
995 
1005  protected function _getCategorySelect($sFields, $sCatId, $aSessionFilter)
1006  {
1007  $sArticleTable = getViewName('oxarticles');
1008  $sO2CView = getViewName('oxobject2category');
1009 
1010  // ----------------------------------
1011  // sorting
1012  $sSorting = '';
1013  if ($this->_sCustomSorting) {
1014  $sSorting = " {$this->_sCustomSorting} , ";
1015  }
1016 
1017  // ----------------------------------
1018  // filtering ?
1019  $sFilterSql = '';
1020  $iLang = oxRegistry::getLang()->getBaseLanguage();
1021  if ($aSessionFilter && isset($aSessionFilter[$sCatId][$iLang])) {
1022  $sFilterSql = $this->_getFilterSql($sCatId, $aSessionFilter[$sCatId][$iLang]);
1023  }
1024 
1025  $oDb = oxDb::getDb();
1026 
1027  $sSelect = "SELECT $sFields, $sArticleTable.oxtimestamp FROM $sO2CView as oc left join $sArticleTable
1028  ON $sArticleTable.oxid = oc.oxobjectid
1029  WHERE " . $this->getBaseObject()->getSqlActiveSnippet() . " and $sArticleTable.oxparentid = ''
1030  and oc.oxcatnid = " . $oDb->quote($sCatId) . " $sFilterSql ORDER BY $sSorting oc.oxpos, oc.oxobjectid ";
1031 
1032  return $sSelect;
1033  }
1034 
1043  protected function _getCategoryCountSelect($sCatId, $aSessionFilter)
1044  {
1045  $sArticleTable = getViewName('oxarticles');
1046  $sO2CView = getViewName('oxobject2category');
1047 
1048 
1049  // ----------------------------------
1050  // filtering ?
1051  $sFilterSql = '';
1052  $iLang = oxRegistry::getLang()->getBaseLanguage();
1053  if ($aSessionFilter && isset($aSessionFilter[$sCatId][$iLang])) {
1054  $sFilterSql = $this->_getFilterSql($sCatId, $aSessionFilter[$sCatId][$iLang]);
1055  }
1056 
1057  $oDb = oxDb::getDb();
1058 
1059  $sSelect = "SELECT COUNT(*) FROM $sO2CView as oc left join $sArticleTable
1060  ON $sArticleTable.oxid = oc.oxobjectid
1061  WHERE " . $this->getBaseObject()->getSqlActiveSnippet() . " and $sArticleTable.oxparentid = ''
1062  and oc.oxcatnid = " . $oDb->quote($sCatId) . " $sFilterSql ";
1063 
1064  return $sSelect;
1065  }
1066 
1074  protected function _getSearchSelect($sSearchString)
1075  {
1076  // check if it has string at all
1077  if (!$sSearchString || !str_replace(' ', '', $sSearchString)) {
1078  return '';
1079  }
1080 
1081  $oDb = oxDb::getDb();
1082  $myConfig = $this->getConfig();
1083  $myUtils = oxRegistry::getUtils();
1084  $sArticleTable = $this->getBaseObject()->getViewName();
1085 
1086  $aSearch = explode(' ', $sSearchString);
1087 
1088  $sSearch = ' and ( ';
1089  $blSep = false;
1090 
1091  // #723
1092  if ($myConfig->getConfigParam('blSearchUseAND')) {
1093  $sSearchSep = ' and ';
1094  } else {
1095  $sSearchSep = ' or ';
1096  }
1097 
1098  $aSearchCols = $myConfig->getConfigParam('aSearchCols');
1099  $oBaseObject = $this->getBaseObject();
1100  $myUtilsString = oxRegistry::get("oxUtilsString");
1101  foreach ($aSearch as $sSearchString) {
1102 
1103  if (!strlen($sSearchString)) {
1104  continue;
1105  }
1106 
1107  if ($blSep) {
1108  $sSearch .= $sSearchSep;
1109  }
1110  $blSep2 = false;
1111  $sSearch .= '( ';
1112 
1113  $sUml = $myUtilsString->prepareStrForSearch($sSearchString);
1114  foreach ($aSearchCols as $sField) {
1115 
1116  if ($blSep2) {
1117  $sSearch .= ' or ';
1118  }
1119 
1120  // as long description now is on different table table must differ
1121  if ($sField == 'oxlongdesc' || $sField == 'oxtags') {
1122  $sSearchTable = getViewName('oxartextends');
1123  } else {
1124  $sSearchTable = $sArticleTable;
1125  }
1126 
1127  $sSearch .= $sSearchTable . '.' . $sField . ' like ' . $oDb->quote('%' . $sSearchString . '%') . ' ';
1128  if ($sUml) {
1129  $sSearch .= ' or ' . $sSearchTable . '.' . $sField . ' like ' . $oDb->quote('%' . $sUml . '%');
1130  }
1131  $blSep2 = true;
1132  }
1133  $sSearch .= ' ) ';
1134  $blSep = true;
1135  }
1136  $sSearch .= ' ) ';
1137 
1138  return $sSearch;
1139  }
1140 
1149  protected function _getPriceSelect($dPriceFrom, $dPriceTo)
1150  {
1151  $oBaseObject = $this->getBaseObject();
1152  $sArticleTable = $oBaseObject->getViewName();
1153  $sSelectFields = $oBaseObject->getSelectFields();
1154 
1155  $sSubSelect = "";
1156 
1157  $sSelect = "select {$sSelectFields} from {$sArticleTable} where oxvarminprice >= 0 ";
1158  $sSelect .= $dPriceTo ? "and oxvarminprice <= " . (double) $dPriceTo . " " : " ";
1159  $sSelect .= $dPriceFrom ? "and oxvarminprice >= " . (double) $dPriceFrom . " " : " ";
1160 
1161  $sSelect .= " and " . $oBaseObject->getSqlActiveSnippet() . " and {$sArticleTable}.oxissearch = 1";
1162 
1163  if (!$this->_sCustomSorting) {
1164  $sSelect .= " order by {$sArticleTable}.oxvarminprice asc , {$sArticleTable}.oxid";
1165  } else {
1166  $sSelect .= " order by {$this->_sCustomSorting}, {$sArticleTable}.oxid ";
1167  }
1168 
1169  return $sSelect;
1170  }
1171 
1179  protected function _getVendorSelect($sVendorId)
1180  {
1181  $sArticleTable = getViewName('oxarticles');
1182  $oBaseObject = $this->getBaseObject();
1183  $sFieldNames = $oBaseObject->getSelectFields();
1184  $sSelect = "select $sFieldNames from $sArticleTable ";
1185  $sSelect .= "where $sArticleTable.oxvendorid = " . oxDb::getDb()->quote($sVendorId) . " ";
1186  $sSelect .= " and " . $oBaseObject->getSqlActiveSnippet() . " and $sArticleTable.oxparentid = '' ";
1187 
1188  if ($this->_sCustomSorting) {
1189  $sSelect .= " ORDER BY {$this->_sCustomSorting} ";
1190  }
1191 
1192  return $sSelect;
1193  }
1194 
1202  protected function _getManufacturerSelect($sManufacturerId)
1203  {
1204  $sArticleTable = getViewName('oxarticles');
1205  $oBaseObject = $this->getBaseObject();
1206  $sFieldNames = $oBaseObject->getSelectFields();
1207  $sSelect = "select $sFieldNames from $sArticleTable ";
1208  $sSelect .= "where $sArticleTable.oxmanufacturerid = " . oxDb::getDb()->quote($sManufacturerId) . " ";
1209  $sSelect .= " and " . $oBaseObject->getSqlActiveSnippet() . " and $sArticleTable.oxparentid = '' ";
1210 
1211  if ($this->_sCustomSorting) {
1212  $sSelect .= " ORDER BY {$this->_sCustomSorting} ";
1213  }
1214 
1215  return $sSelect;
1216  }
1217 
1223  protected function _canUpdatePrices()
1224  {
1225  $oConfig = $this->getConfig();
1226  $blCan = false;
1227 
1228  // crontab is off?
1229  if (!$oConfig->getConfigParam("blUseCron")) {
1230  $iTimeToUpdate = $oConfig->getConfigParam("iTimeToUpdatePrices");
1231  if (!$iTimeToUpdate || $iTimeToUpdate <= oxRegistry::get("oxUtilsDate")->getTime()) {
1232  $blCan = true;
1233  }
1234  }
1235 
1236  return $blCan;
1237  }
1238 }