Go to the documentation of this file.00001 <?php
00002
00007 class oxBasketReservation extends oxSuperCfg
00008 {
00009
00015 protected $_oReservations = null;
00016
00022 protected $_aCurrentlyReserved = null;
00023
00029 protected function _getReservationsId()
00030 {
00031 $sId = oxRegistry::getSession()->getVariable('basketReservationToken');
00032 if (!$sId) {
00033 $sId = oxUtilsObject::getInstance()->generateUId();
00034 oxRegistry::getSession()->setVariable('basketReservationToken', $sId);
00035 }
00036
00037 return $sId;
00038 }
00039
00047 protected function _loadReservations($sBasketId)
00048 {
00049 $oReservations = oxNew('oxuserbasket');
00050 $aWhere = array('oxuserbaskets.oxuserid' => $sBasketId, 'oxuserbaskets.oxtitle' => 'reservations');
00051
00052
00053 if (!$oReservations->assignRecord($oReservations->buildSelectString($aWhere))) {
00054 $oReservations->oxuserbaskets__oxtitle = new oxField('reservations');
00055 $oReservations->oxuserbaskets__oxuserid = new oxField($sBasketId);
00056
00057 $oReservations->setIsNewBasket();
00058 }
00059
00060 return $oReservations;
00061 }
00062
00068 public function getReservations()
00069 {
00070 if ($this->_oReservations) {
00071 return $this->_oReservations;
00072 }
00073
00074 if (!$sBasketId = $this->_getReservationsId()) {
00075 return null;
00076 }
00077
00078 $this->_oReservations = $this->_loadReservations($sBasketId);
00079
00080 return $this->_oReservations;
00081 }
00082
00088 protected function _getReservedItems()
00089 {
00090 if (isset($this->_aCurrentlyReserved)) {
00091 return $this->_aCurrentlyReserved;
00092 }
00093
00094 $oReserved = $this->getReservations();
00095 if (!$oReserved) {
00096 return array();
00097 }
00098
00099 $this->_aCurrentlyReserved = array();
00100 foreach ($oReserved->getItems(false, false) as $oItem) {
00101 if (!isset($this->_aCurrentlyReserved[$oItem->oxuserbasketitems__oxartid->value])) {
00102 $this->_aCurrentlyReserved[$oItem->oxuserbasketitems__oxartid->value] = 0;
00103 }
00104 $this->_aCurrentlyReserved[$oItem->oxuserbasketitems__oxartid->value] += $oItem->oxuserbasketitems__oxamount->value;
00105 }
00106
00107 return $this->_aCurrentlyReserved;
00108 }
00109
00117 public function getReservedAmount($sArticleId)
00118 {
00119 $aCurrentlyReserved = $this->_getReservedItems();
00120 if (isset($aCurrentlyReserved[$sArticleId])) {
00121 return $aCurrentlyReserved[$sArticleId];
00122 }
00123
00124 return 0;
00125 }
00126
00134 protected function _basketDifference(oxBasket $oBasket)
00135 {
00136 $aDiff = $this->_getReservedItems();
00137
00138 foreach ($oBasket->getContents() as $oItem) {
00139 $sProdId = $oItem->getProductId();
00140 if (!isset($aDiff[$sProdId])) {
00141 $aDiff[$sProdId] = -$oItem->getAmount();
00142 } else {
00143 $aDiff[$sProdId] -= $oItem->getAmount();
00144 }
00145 }
00146
00147 return $aDiff;
00148 }
00149
00157 protected function _reserveArticles($aBasketDiff)
00158 {
00159 $blAllowNegativeStock = $this->getConfig()->getConfigParam('blAllowNegativeStock');
00160
00161 $oReserved = $this->getReservations();
00162 foreach ($aBasketDiff as $sId => $dAmount) {
00163 if ($dAmount != 0) {
00164 $oArticle = oxNew('oxarticle');
00165 if ($oArticle->load($sId)) {
00166 $oArticle->reduceStock(-$dAmount, $blAllowNegativeStock);
00167 $oReserved->addItemToBasket($sId, -$dAmount);
00168 }
00169 }
00170 }
00171 $this->_aCurrentlyReserved = null;
00172 }
00173
00179 public function reserveBasket(oxBasket $oBasket)
00180 {
00181 $this->_reserveArticles($this->_basketDifference($oBasket));
00182 }
00183
00192 public function commitArticleReservation($sArticleId, $dAmount)
00193 {
00194 $dReserved = $this->getReservedAmount($sArticleId);
00195
00196 if ($dReserved < $dAmount) {
00197 $dAmount = $dReserved;
00198 }
00199
00200 $oArticle = oxNew('oxarticle');
00201 $oArticle->load($sArticleId);
00202
00203 $this->getReservations()->addItemToBasket($sArticleId, -$dAmount);
00204 $oArticle->beforeUpdate();
00205 $oArticle->updateSoldAmount($dAmount);
00206 $this->_aCurrentlyReserved = null;
00207 }
00208
00215 public function discardArticleReservation($sArticleId)
00216 {
00217 $dReserved = $this->getReservedAmount($sArticleId);
00218 if ($dReserved) {
00219 $oArticle = oxNew('oxarticle');
00220 if ($oArticle->load($sArticleId)) {
00221 $oArticle->reduceStock(-$dReserved, true);
00222 $this->getReservations()->addItemToBasket($sArticleId, 0, null, true);
00223 $this->_aCurrentlyReserved = null;
00224 }
00225 }
00226 }
00227
00231 public function discardReservations()
00232 {
00233 foreach (array_keys($this->_getReservedItems()) as $sArticleId) {
00234 $this->discardArticleReservation($sArticleId);
00235 }
00236 if ($this->_oReservations) {
00237 $this->_oReservations->delete();
00238 $this->_oReservations = null;
00239 $this->_aCurrentlyReserved = null;
00240 }
00241 }
00242
00251 public function discardUnusedReservations($iLimit)
00252 {
00253 $oDb = oxDb::getDb(oxDb::FETCH_MODE_ASSOC);
00254 $iStartTime = oxRegistry::get("oxUtilsDate")->getTime() - (int) $this->getConfig()->getConfigParam('iPsBasketReservationTimeout');
00255 $oRs = $oDb->select("select oxid from oxuserbaskets where oxtitle = 'reservations' and oxupdate <= $iStartTime limit $iLimit", false, false);
00256 if ($oRs->EOF) {
00257 return;
00258 }
00259 $aFinished = array();
00260 while (!$oRs->EOF) {
00261 $aFinished[] = $oDb->quote($oRs->fields['oxid']);
00262 $oRs->MoveNext();
00263 }
00264 $oRs = $oDb->select("select oxartid, oxamount from oxuserbasketitems where oxbasketid in (" . implode(",", $aFinished) . ")", false, false);
00265 while (!$oRs->EOF) {
00266 $oArticle = oxNew('oxarticle');
00267 if ($oArticle->load($oRs->fields['oxartid'])) {
00268 $oArticle->reduceStock(-$oRs->fields['oxamount'], true);
00269 }
00270 $oRs->MoveNext();
00271 }
00272 $oDb->execute("delete from oxuserbasketitems where oxbasketid in (" . implode(",", $aFinished) . ")");
00273 $oDb->execute("delete from oxuserbaskets where oxid in (" . implode(",", $aFinished) . ")");
00274
00275
00276 $oDb->execute("delete from oxuserbaskets where oxtitle = 'savedbasket' and oxupdate <= $iStartTime");
00277
00278 $this->_aCurrentlyReserved = null;
00279 }
00280
00286 public function getTimeLeft()
00287 {
00288 $iTimeout = $this->getConfig()->getConfigParam('iPsBasketReservationTimeout');
00289 if ($iTimeout > 0) {
00290 $oRev = $this->getReservations();
00291 if ($oRev && $oRev->getId()) {
00292 $iTimeout -= (oxRegistry::get("oxUtilsDate")->getTime() - (int) $oRev->oxuserbaskets__oxupdate->value);
00293 oxRegistry::getSession()->setVariable("iBasketReservationTimeout", $oRev->oxuserbaskets__oxupdate->value);
00294 } elseif (($iSessionTimeout = oxRegistry::getSession()->getVariable("iBasketReservationTimeout"))) {
00295 $iTimeout -= (oxRegistry::get("oxUtilsDate")->getTime() - (int) $iSessionTimeout);
00296 }
00297
00298 return $iTimeout < 0 ? 0 : $iTimeout;
00299 }
00300
00301 return 0;
00302 }
00303
00307 public function renewExpiration()
00308 {
00309 if ($oReserved = $this->getReservations()) {
00310 $iTime = oxRegistry::get("oxUtilsDate")->getTime();
00311 $oReserved->oxuserbaskets__oxupdate = new oxField($iTime);
00312 $oReserved->save();
00313
00314 oxRegistry::getSession()->deleteVariable("iBasketReservationTimeout");
00315 }
00316 }
00317 }