oxdiscount.php

Go to the documentation of this file.
00001 <?php
00002 
00007 class oxDiscount extends oxI18n
00008 {
00014     protected $_sClassName = 'oxdiscount';
00015 
00021     protected $_dAmount = null;
00022 
00028     protected $_sBasketIdent = null;
00029 
00035     protected $_blIsForArticleOrForCategory = null;
00036 
00042     protected $_aHasArticleDiscounts = array();
00043 
00047     public function __construct()
00048     {
00049         parent::__construct();
00050         $this->init( 'oxdiscount' );
00051     }
00052 
00060     public function delete( $sOXID = null )
00061     {
00062         if ( !$sOXID ) {
00063             $sOXID = $this->getId();
00064         }
00065         if ( !$sOXID ) {
00066             return false;
00067         }
00068 
00069 
00070         $oDb = oxDb::getDb();
00071         $oDb->execute( 'delete from oxobject2discount where oxobject2discount.oxdiscountid = '.$oDb->quote($sOXID) );
00072 
00073         return parent::delete( $sOXID );
00074     }
00075 
00083     public function isForArticle( $oArticle )
00084     {
00085 
00086         // item discounts may only be applied for basket
00087         if ( $this->oxdiscount__oxaddsumtype->value == 'itm' ) {
00088             return false;
00089         }
00090 
00091         if ( $this->oxdiscount__oxamount->value || $this->oxdiscount__oxprice->value ) {
00092             return false;
00093         }
00094 
00095         if ( $this->oxdiscount__oxpriceto->value && ($this->oxdiscount__oxpriceto->value < $oArticle->getBasePrice()) ) {
00096             return false;
00097         }
00098 
00099         $oDb = oxDb::getDb();
00100 
00101         $sDiscountIdQuoted = $oDb->quote($this->oxdiscount__oxid->value);
00102 
00103         //check for global discount (no articles, no categories)
00104         if ( $this->_blIsForArticleOrForCategory ) {
00105             return true;
00106         } elseif ( $this->_blIsForArticleOrForCategory === null ) {
00107 
00108             $this->_blIsForArticleOrForCategory = false;
00109             $sQ = "select 1 from oxobject2discount where oxdiscountid = $sDiscountIdQuoted and ( oxtype = 'oxarticles' or oxtype = 'oxcategories')";
00110             if ( ! $oDb->getOne( $sQ ) ) {
00111                 $this->_blIsForArticleOrForCategory = true;
00112                 return true;
00113             }
00114         }
00115 
00116         $sArticleId = $oArticle->getProductId();
00117 
00118         if ( !$this->_blIsForArticleAndForCategory && !isset($this->_aHasArticleDiscounts[ $sArticleId ] ) ) {
00119 
00120             $this->_aHasArticleDiscounts[ $sArticleId ] = false ;
00121 
00122             // check if this article is assigned
00123             $sQ  = "select 1 from oxobject2discount where oxdiscountid = {$sDiscountIdQuoted} and oxtype = 'oxarticles' ";
00124             $sQ .= $this->_getProductCheckQuery( $oArticle );
00125 
00126             if ( $oDb->getOne( $sQ ) ) {
00127                 $this->_aHasArticleDiscounts[ $sArticleId ] = true;
00128                 return true;
00129             } else {
00130                 // check if article is in some assigned category
00131                 $aCatIds = $oArticle->getCategoryIds();
00132                 if (!$aCatIds || !count($aCatIds)) {
00133                     // no categories are set for article, so no discounts from categories..
00134                     return false;
00135                 }
00136                 $sCatIds = "(".implode(",", oxDb::getInstance()->quoteArray($aCatIds)).")";
00137                 // getOne appends limit 1, so this one should be fast enough
00138                 $sQ = "select 1 from oxobject2discount where oxdiscountid = {$sDiscountIdQuoted} and oxobjectid in $sCatIds and oxtype = 'oxcategories'";
00139                 if ( $oDb->getOne( $sQ ) ) {
00140                     $this->_aHasArticleDiscounts[ $sArticleId ] = true;
00141                     return true;
00142                 }
00143             }
00144         }
00145 
00146         return $this->_aHasArticleDiscounts[ $sArticleId ];
00147     }
00148 
00156     public function isForBasketItem( $oArticle )
00157     {
00158         if ( $this->oxdiscount__oxamount->value == 0 && $this->oxdiscount__oxprice->value == 0 ) {
00159             return false;
00160         }
00161 
00162         // skipping bundle discounts
00163         if ( $this->oxdiscount__oxaddsumtype->value == 'itm' ) {
00164             return false;
00165         }
00166 
00167         $oDb = oxDb::getDb();
00168 
00169         // check if this article is assigned
00170         $sQ  = "select 1 from oxobject2discount where oxdiscountid = ".$oDb->quote( $this->oxdiscount__oxid->value)." and oxtype = 'oxarticles' ";
00171         $sQ .= $this->_getProductCheckQuery( $oArticle );
00172         if ( !( $blOk = ( bool ) $oDb->getOne( $sQ ) ) ) {
00173 
00174             // checkin article cateogry
00175             $blOk = $this->_checkForArticleCategories( $oArticle );
00176         }
00177 
00178         return $blOk;
00179     }
00180 
00188     public function isForBasketAmount( $oBasket )
00189     {
00190         $dAmount = 0;
00191         $aBasketItems = $oBasket->getContents();
00192         foreach ( $aBasketItems as $oBasketItem ) {
00193 
00194             $oBasketArticle = $oBasketItem->getArticle(false);
00195 
00196             $blForBasketItem = false;
00197             if ( $this->oxdiscount__oxaddsumtype->value != 'itm' ) {
00198                 $blForBasketItem = $this->isForBasketItem( $oBasketArticle );
00199             } else {
00200                 $blForBasketItem = $this->isForBundleItem( $oBasketArticle );
00201             }
00202 
00203             if ( $blForBasketItem ) {
00204                 $dRate = $oBasket->getBasketCurrency()->rate;
00205                 if ( $this->oxdiscount__oxprice->value ) {
00206                     if ( ( $oPrice = $oBasketArticle->getPrice() ) ) {
00207                         $dAmount += ($oPrice->getPrice() * $oBasketItem->getAmount())/$dRate;
00208                     }
00209                 } elseif ( $this->oxdiscount__oxamount->value ) {
00210                     $dAmount += $oBasketItem->getAmount();
00211                 }
00212             }
00213         }
00214 
00215         return $this->isForAmount( $dAmount );
00216     }
00217 
00225     public function isForAmount( $dAmount )
00226     {
00227         $blIs = true;
00228 
00229         if ( $this->oxdiscount__oxprice->value &&
00230             ( $dAmount < $this->oxdiscount__oxprice->value || $dAmount > $this->oxdiscount__oxpriceto->value ) ) {
00231             $blIs = false;
00232         } elseif ( $this->oxdiscount__oxamount->value &&
00233             ( $dAmount < $this->oxdiscount__oxamount->value || $dAmount > $this->oxdiscount__oxamountto->value ) ) {
00234             $blIs = false;
00235         }
00236 
00237         return $blIs;
00238     }
00239 
00247     public function isForBasket( $oBasket )
00248     {
00249         // initial configuration check
00250         if ( $this->oxdiscount__oxamount->value == 0 && $this->oxdiscount__oxprice->value == 0 ) {
00251             return false;
00252         }
00253 
00254         $oSummary = $oBasket->getBasketSummary();
00255         // amounts check
00256         if ( $this->oxdiscount__oxamount->value && ( $oSummary->iArticleCount < $this->oxdiscount__oxamount->value || $oSummary->iArticleCount > $this->oxdiscount__oxamountto->value ) ) {
00257             return false;
00258             // price check
00259         } elseif ($this->oxdiscount__oxprice->value) {
00260             $dRate = $oBasket->getBasketCurrency()->rate;
00261             if ( $oSummary->dArticleDiscountablePrice < $this->oxdiscount__oxprice->value*$dRate || $oSummary->dArticleDiscountablePrice > $this->oxdiscount__oxpriceto->value*$dRate ) {
00262                 return false;
00263             }
00264         }
00265 
00266         // oxobject2discount configuration check
00267         $oDb = oxDb::getDb();
00268         $sQ = 'select 1 from oxobject2discount where oxdiscountid = ' . $oDb->quote($this->oxdiscount__oxid->value).' and oxtype in ("oxarticles", "oxcategories" ) ';
00269 
00270         return !( (bool) $oDb->getOne( $sQ ) );
00271     }
00272 
00280     public function isForBundleItem( $oArticle )
00281     {
00282         if ( $this->oxdiscount__oxaddsumtype->value != 'itm' ) {
00283             return false;
00284         }
00285 
00286         $oDb = oxDb::getDb();
00287         $sQ  = "select 1 from oxobject2discount where oxdiscountid=".$oDb->quote( $this->getId() );
00288         $sQ .= $this->_getProductCheckQuery( $oArticle );
00289         if ( !( $blOk = (bool) $oDb->getOne( $sQ ) ) ) {
00290             // additional checks for amounts and other dependencies
00291             $blOk = $this->_checkForArticleCategories( $oArticle );
00292         }
00293         return $blOk;
00294     }
00295 
00303     public function isForBundleBasket( $oBasket )
00304     {
00305         if ( $this->oxdiscount__oxaddsumtype->value != 'itm' ) {
00306             return false;
00307         }
00308 
00309         return $this->isForBasket( $oBasket );
00310     }
00311 
00320     public function getAbsValue( $dPrice, $dAmount = 1 )
00321     {
00322         if ( $this->oxdiscount__oxaddsumtype->value == '%' ) {
00323             return $dPrice * ( $this->oxdiscount__oxaddsum->value / 100 );
00324         } else {
00325             $oCur = $this->getConfig()->getActShopCurrencyObject();
00326             return $this->oxdiscount__oxaddsum->value * $dAmount * $oCur->rate;
00327         }
00328     }
00329 
00340     public function applyDiscount( $oPrice, $dAmount = 1 )
00341     {
00342         if ( $this->oxdiscount__oxaddsumtype->value == 'abs' ) {
00343             $oCur = $this->getConfig()->getActShopCurrencyObject();
00344             $oPrice->subtract( $this->oxdiscount__oxaddsum->value * $oCur->rate );
00345         } else {
00346             $oPrice->multiply( (100 - $this->oxdiscount__oxaddsum->value) / 100 );
00347         }
00348 
00349         if ( $oPrice->getBruttoPrice() < 0 || $oPrice->getNettoPrice() < 0 ) {
00350             $oPrice->setPrice(0);
00351         }
00352     }
00353 
00361     public function getPercentage( $dPrice )
00362     {
00363         if ( $this->getAddSumType() == 'abs' && $dPrice > 0 ) {
00364             return $this->getAddSum() / $dPrice * 100;
00365         } else {
00366             return $this->getAddSum();
00367         }
00368     }
00369 
00370 
00371 
00378     public function getAddSum()
00379     {
00380         if ( $this->oxdiscount__oxaddsumtype->value == 'abs' ) {
00381             $oCur = $this->getConfig()->getActShopCurrencyObject();
00382             return $this->oxdiscount__oxaddsum->value * $oCur->rate;
00383         } else {
00384             return $this->oxdiscount__oxaddsum->value;
00385         }
00386     }
00387 
00393     public function getAddSumType()
00394     {
00395         return $this->oxdiscount__oxaddsumtype->value;
00396     }
00397 
00398 
00399 
00400 
00408     public function getBundleAmount( $dAmount )
00409     {
00410         $dItemAmount = $this->oxdiscount__oxitmamount->value;
00411 
00412         // Multiplying bundled articles count, if allowed
00413         if ( $this->oxdiscount__oxitmmultiple->value && $this->oxdiscount__oxamount->value > 0 ) {
00414             $dItemAmount = floor( $dAmount / $this->oxdiscount__oxamount->value ) * $this->oxdiscount__oxitmamount->value;
00415         }
00416 
00417         return $dItemAmount;
00418     }
00419 
00427     protected function _checkForArticleCategories( $oArticle )
00428     {
00429         // check if article is in some assigned category
00430         $aCatIds = $oArticle->getCategoryIds();
00431         if (!$aCatIds || !count($aCatIds)) {
00432             // no categories are set for article, so no discounts from categories..
00433             return false;
00434         }
00435 
00436         $sCatIds = "(".implode(",", oxDb::getInstance()->quoteArray($aCatIds)).")";
00437 
00438         $oDb = oxDb::getDb();
00439         // getOne appends limit 1, so this one should be fast enough
00440         $sQ = "select oxobjectid from oxobject2discount where oxdiscountid = ".$oDb->quote($this->oxdiscount__oxid->value)." and oxobjectid in $sCatIds and oxtype = 'oxcategories'";
00441 
00442         return $oDb->getOne( $sQ );
00443     }
00444 
00450     public function getSimpleDiscount()
00451     {
00452         $oDiscount = new stdClass();
00453         $oDiscount->sOXID     = $this->getId();
00454         $oDiscount->sDiscount = $this->oxdiscount__oxtitle->value;
00455         $oDiscount->sType     = $this->oxdiscount__oxaddsumtype->value;
00456 
00457         return $oDiscount;
00458     }
00459 
00465     public function getArticleIds()
00466     {
00467         return oxDb::getDb()->getCol("select `oxobjectid` from oxobject2discount where oxdiscountid = '".$this->getId()."' and oxtype = 'oxarticles'");
00468     }
00469 
00475     public function getCategoryIds()
00476     {
00477         return oxDb::getDb()->getCol("select `oxobjectid` from oxobject2discount where oxdiscountid = '".$this->getId()."' and oxtype = 'oxcategories'");
00478     }
00479 
00488     protected function _getProductCheckQuery( $oProduct )
00489     {
00490         $oDb = oxDb::getDb();
00491         // check if this article is assigned
00492         if ( ( $sParentId = $oProduct->getProductParentId() ) ) {
00493             $sArticleId = " and ( oxobjectid = ".$oDb->quote( $oProduct->getProductId() )." or oxobjectid = ".$oDb->quote( $sParentId ) . " )";
00494         } else {
00495             $sArticleId = " and oxobjectid = ".$oDb->quote( $oProduct->getProductId() );
00496         }
00497 
00498         return $sArticleId;
00499     }
00500 
00501 
00502 }