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->getBruttoPrice() * $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         return $blIs;
00237     }
00238 
00246     public function isForBasket( $oBasket )
00247     {
00248         // initial configuration check
00249         if ( $this->oxdiscount__oxamount->value == 0 && $this->oxdiscount__oxprice->value == 0 ) {
00250             return false;
00251         }
00252 
00253         $oSummary = $oBasket->getBasketSummary();
00254         // amounts check
00255         if ( $this->oxdiscount__oxamount->value && ( $oSummary->iArticleCount < $this->oxdiscount__oxamount->value || $oSummary->iArticleCount > $this->oxdiscount__oxamountto->value ) ) {
00256             return false;
00257             // price check
00258         } elseif ($this->oxdiscount__oxprice->value) {
00259             $dRate = $oBasket->getBasketCurrency()->rate;
00260             if ( $oSummary->dArticleDiscountablePrice < $this->oxdiscount__oxprice->value*$dRate || $oSummary->dArticleDiscountablePrice > $this->oxdiscount__oxpriceto->value*$dRate ) {
00261                 return false;
00262             }
00263         }
00264 
00265         // oxobject2discount configuration check
00266         $oDb = oxDb::getDb();
00267         $sQ = 'select 1 from oxobject2discount where oxdiscountid = ' . $oDb->quote($this->oxdiscount__oxid->value).' and oxtype in ("oxarticles", "oxcategories" ) ';
00268 
00269         return !( (bool) $oDb->getOne( $sQ ) );
00270     }
00271 
00279     public function isForBundleItem( $oArticle )
00280     {
00281         if ( $this->oxdiscount__oxaddsumtype->value != 'itm' ) {
00282             return false;
00283         }
00284 
00285         $oDb = oxDb::getDb();
00286         $sQ  = "select 1 from oxobject2discount where oxdiscountid=".$oDb->quote( $this->getId() );
00287         $sQ .= $this->_getProductCheckQuery( $oArticle );
00288         if ( !( $blOk = (bool) $oDb->getOne( $sQ ) ) ) {
00289             // additional checks for amounts and other dependencies
00290             $blOk = $this->_checkForArticleCategories( $oArticle );
00291         }
00292         return $blOk;
00293     }
00294 
00302     public function isForBundleBasket( $oBasket )
00303     {
00304         if ( $this->oxdiscount__oxaddsumtype->value != 'itm' ) {
00305             return false;
00306         }
00307 
00308         return $this->isForBasket( $oBasket );
00309     }
00310 
00319     public function getAbsValue( $dPrice, $dAmount = 1 )
00320     {
00321         if ( $this->oxdiscount__oxaddsumtype->value == '%' ) {
00322             return $dPrice * ( $this->oxdiscount__oxaddsum->value / 100 );
00323         } else {
00324             $oCur = $this->getConfig()->getActShopCurrencyObject();
00325             return $this->oxdiscount__oxaddsum->value * $dAmount * $oCur->rate;
00326         }
00327     }
00328 
00337     public function applyDiscount( $oPrice, $dAmount = 1 )
00338     {
00339         if ( $this->oxdiscount__oxaddsumtype->value == 'abs' ) {
00340             $oCur = $this->getConfig()->getActShopCurrencyObject();
00341             $oPrice->subtract( $this->oxdiscount__oxaddsum->value * $oCur->rate );
00342         } else {
00343             $oPrice->multiply( (100 - $this->oxdiscount__oxaddsum->value) / 100 );
00344         }
00345 
00346         if ( $oPrice->getBruttoPrice() < 0 || $oPrice->getNettoPrice() < 0 ) {
00347             $oPrice->setPrice(0);
00348         }
00349     }
00350 
00358     public function getPercentage( $dPrice )
00359     {
00360         if ( $this->getAddSumType() == 'abs' ) {
00361             return $this->getAddSum() / $dPrice * 100;
00362         } else {
00363             return $this->getAddSum();
00364         }
00365     }
00366 
00367 
00368 
00375     public function getAddSum()
00376     {
00377         if ( $this->oxdiscount__oxaddsumtype->value == 'abs' ) {
00378             $oCur = $this->getConfig()->getActShopCurrencyObject();
00379             return $this->oxdiscount__oxaddsum->value * $oCur->rate;
00380         } else {
00381             return $this->oxdiscount__oxaddsum->value;
00382         }
00383     }
00384 
00390     public function getAddSumType()
00391     {
00392         return $this->oxdiscount__oxaddsumtype->value;
00393     }
00394 
00395 
00396 
00397 
00405     public function getBundleAmount( $dAmount )
00406     {
00407         $dItemAmount = $this->oxdiscount__oxitmamount->value;
00408 
00409         // Multiplying bundled articles count, if allowed
00410         if ( $this->oxdiscount__oxitmmultiple->value && $this->oxdiscount__oxamount->value > 0 ) {
00411             $dItemAmount = floor( $dAmount / $this->oxdiscount__oxamount->value ) * $this->oxdiscount__oxitmamount->value;
00412         }
00413 
00414         return $dItemAmount;
00415     }
00416 
00424     protected function _checkForArticleCategories( $oArticle )
00425     {
00426         // check if article is in some assigned category
00427         $aCatIds = $oArticle->getCategoryIds();
00428         if (!$aCatIds || !count($aCatIds)) {
00429             // no categories are set for article, so no discounts from categories..
00430             return false;
00431         }
00432 
00433         $sCatIds = "(".implode(",", oxDb::getInstance()->quoteArray($aCatIds)).")";
00434 
00435         $oDb = oxDb::getDb();
00436         // getOne appends limit 1, so this one should be fast enough
00437         $sQ = "select oxobjectid from oxobject2discount where oxdiscountid = ".$oDb->quote($this->oxdiscount__oxid->value)." and oxobjectid in $sCatIds and oxtype = 'oxcategories'";
00438 
00439         return $oDb->getOne( $sQ );
00440     }
00441 
00447     public function getSimpleDiscount()
00448     {
00449         $oDiscount = new stdClass();
00450         $oDiscount->sOXID     = $this->getId();
00451         $oDiscount->sDiscount = $this->oxdiscount__oxtitle->value;
00452         $oDiscount->sType     = $this->oxdiscount__oxaddsumtype->value;
00453 
00454         return $oDiscount;
00455     }
00456 
00462     public function getArticleIds()
00463     {
00464         return oxDb::getDb()->getCol("select `oxobjectid` from oxobject2discount where oxdiscountid = '".$this->getId()."' and oxtype = 'oxarticles'");
00465     }
00466 
00472     public function getCategoryIds()
00473     {
00474         return oxDb::getDb()->getCol("select `oxobjectid` from oxobject2discount where oxdiscountid = '".$this->getId()."' and oxtype = 'oxcategories'");
00475     }
00476 
00485     protected function _getProductCheckQuery( $oProduct )
00486     {
00487         $oDb = oxDb::getDb();
00488         // check if this article is assigned
00489         if ( ( $sParentId = $oProduct->getProductParentId() ) ) {
00490             $sArticleId = " and ( oxobjectid = ".$oDb->quote( $oProduct->getProductId() )." or oxobjectid = ".$oDb->quote( $sParentId ) . " )";
00491         } else {
00492             $sArticleId = " and oxobjectid = ".$oDb->quote( $oProduct->getProductId() );
00493         }
00494 
00495         return $sArticleId;
00496     }
00497 
00498 
00499 }