Mage_Core_Modules - Version 1.8.1.0

Version Notes

1.8.1.0

Download this release

Release Info

Developer Magento Core Team
Extension Mage_Core_Modules
Version 1.8.1.0
Comparing to
See all releases


Code changes from version 1.8.0.0 to 1.8.1.0

Files changed (181) hide show
  1. app/Mage.php +2 -1
  2. app/code/core/Mage/Api/Model/Server/Adapter/Soap.php +4 -2
  3. app/code/core/Mage/Bundle/Block/Catalog/Product/View/Type/Bundle.php +59 -8
  4. app/code/core/Mage/Bundle/Block/Catalog/Product/View/Type/Bundle/Option.php +12 -10
  5. app/code/core/Mage/Bundle/Model/Product/Price.php +133 -68
  6. app/code/core/Mage/Catalog/Block/Product/Abstract.php +23 -7
  7. app/code/core/Mage/Catalog/Block/Product/Price.php +42 -1
  8. app/code/core/Mage/Catalog/Block/Product/View.php +9 -2
  9. app/code/core/Mage/Catalog/Helper/Product/Compare.php +2 -1
  10. app/code/core/Mage/Catalog/Model/Resource/Product/Indexer/Eav/Source.php +2 -1
  11. app/code/core/Mage/Catalog/Model/Resource/Product/Option/Value.php +3 -3
  12. app/code/core/Mage/Catalog/Model/Resource/Product/Status.php +6 -10
  13. app/code/core/Mage/Catalog/Model/Resource/Product/Type/Configurable.php +1 -1
  14. app/code/core/Mage/Catalog/controllers/Product/CompareController.php +5 -0
  15. app/code/core/Mage/Catalog/etc/wsi.xml +2 -2
  16. app/code/core/Mage/CatalogInventory/Model/Observer.php +18 -8
  17. app/code/core/Mage/CatalogRule/Model/Resource/Rule.php +1 -1
  18. app/code/core/Mage/CatalogRule/Model/Rule/Condition/Product.php +3 -1
  19. app/code/core/Mage/CatalogSearch/Helper/Data.php +19 -2
  20. app/code/core/Mage/Checkout/Block/Cart/Item/Renderer.php +4 -1
  21. app/code/core/Mage/Checkout/Helper/Data.php +55 -29
  22. app/code/core/Mage/Checkout/Model/Cart/Product/Api.php +11 -12
  23. app/code/core/Mage/Checkout/controllers/CartController.php +5 -0
  24. app/code/core/Mage/Checkout/controllers/MultishippingController.php +30 -6
  25. app/code/core/Mage/Cms/Model/Resource/Page.php +3 -0
  26. app/code/core/Mage/Cms/Model/Resource/Page/Service.php +3 -2
  27. app/code/core/Mage/{GoogleCheckout/Block/Form.php → Cms/data/cms_setup/data-upgrade-1.6.0.0.1-1.6.0.0.2.php} +13 -20
  28. app/code/core/Mage/Cms/etc/config.xml +1 -1
  29. app/code/core/Mage/Core/Block/Abstract.php +65 -32
  30. app/code/core/Mage/Core/Helper/Cookie.php +15 -0
  31. app/code/core/Mage/Core/Model/Design/Package.php +3 -0
  32. app/code/core/Mage/Core/Model/Locale.php +23 -4
  33. app/code/core/Mage/Core/Model/Resource/Design.php +20 -30
  34. app/code/core/Mage/Core/Model/Store.php +57 -5
  35. app/code/core/Mage/Core/etc/config.xml +1 -1
  36. app/code/core/Mage/Core/sql/core_setup/mysql4-upgrade-0.7.3-0.7.4.php +1 -1
  37. app/code/core/Mage/{GoogleCheckout/sql/googlecheckout_setup/mysql4-upgrade-1.6.0.0-1.6.0.1.php → Core/sql/core_setup/upgrade-1.6.0.3-1.6.0.4.php} +12 -7
  38. app/code/core/Mage/Customer/Helper/Address.php +1 -1
  39. app/code/core/Mage/Customer/Model/Address/Abstract.php +58 -10
  40. app/code/core/Mage/Customer/controllers/AccountController.php +6 -2
  41. app/code/core/Mage/{GoogleCheckout/sql/googlecheckout_setup/mysql4-upgrade-0.7.3-0.7.4.php → Customer/data/customer_setup/data-upgrade-1.6.2.0.2-1.6.2.0.3.php} +12 -9
  42. app/code/core/Mage/Customer/etc/config.xml +1 -1
  43. app/code/core/Mage/Customer/etc/wsdl.xml +6 -0
  44. app/code/core/Mage/Customer/etc/wsi.xml +6 -0
  45. app/code/core/Mage/Customer/sql/customer_setup/upgrade-1.6.2.0.1-1.6.2.0.2.php +82 -0
  46. app/code/core/Mage/Directory/Model/Currency.php +72 -23
  47. app/code/core/Mage/Directory/Model/Resource/Region/Collection.php +1 -1
  48. app/code/core/Mage/{GoogleCheckout/sql/googlecheckout_setup/mysql4-install-0.7.0.php → Directory/sql/directory_setup/mysql4-upgrade-1.6.0.1-1.6.0.2.php} +27 -14
  49. app/code/core/Mage/{GoogleCheckout/Model/Resource/Api/Debug.php → Eav/Model/Attribute/Data/Datetime.php} +29 -7
  50. app/code/core/Mage/Eav/Model/Entity/Attribute/Backend/Time/Created.php +29 -2
  51. app/code/core/Mage/Eav/Model/Resource/Entity/Attribute.php +2 -2
  52. app/code/core/Mage/Eav/Model/Resource/Entity/Attribute/Option.php +2 -2
  53. app/code/core/Mage/Eav/etc/config.xml +1 -1
  54. app/code/core/Mage/{GoogleCheckout/sql/googlecheckout_setup/mysql4-upgrade-0.7.2-0.7.3.php → Eav/sql/eav_setup/upgrade-1.6.0.0-1.6.0.1.php} +7 -5
  55. app/code/core/Mage/GoogleAnalytics/Block/Ga.php +14 -1
  56. app/code/core/Mage/GoogleAnalytics/Helper/Data.php +14 -2
  57. app/code/core/Mage/GoogleAnalytics/Model/Observer.php +0 -39
  58. app/code/core/Mage/GoogleAnalytics/etc/config.xml +0 -8
  59. app/code/core/Mage/GoogleAnalytics/etc/system.xml +9 -0
  60. app/code/core/Mage/GoogleCheckout/Block/Adminhtml/Shipping/Applicable/Countries.php +0 -65
  61. app/code/core/Mage/GoogleCheckout/Block/Adminhtml/Shipping/Merchant.php +0 -181
  62. app/code/core/Mage/GoogleCheckout/Block/Link.php +0 -108
  63. app/code/core/Mage/GoogleCheckout/Exception.php +0 -30
  64. app/code/core/Mage/GoogleCheckout/Helper/Data.php +0 -192
  65. app/code/core/Mage/GoogleCheckout/Model/Api.php +0 -233
  66. app/code/core/Mage/GoogleCheckout/Model/Api/Debug.php +0 -52
  67. app/code/core/Mage/GoogleCheckout/Model/Api/Xml/Abstract.php +0 -245
  68. app/code/core/Mage/GoogleCheckout/Model/Api/Xml/Callback.php +0 -1107
  69. app/code/core/Mage/GoogleCheckout/Model/Api/Xml/Checkout.php +0 -1143
  70. app/code/core/Mage/GoogleCheckout/Model/Api/Xml/Order.php +0 -181
  71. app/code/core/Mage/GoogleCheckout/Model/Mysql4/Api/Debug.php +0 -37
  72. app/code/core/Mage/GoogleCheckout/Model/Mysql4/Api/Debug/Collection.php +0 -38
  73. app/code/core/Mage/GoogleCheckout/Model/Mysql4/Notification.php +0 -37
  74. app/code/core/Mage/GoogleCheckout/Model/Mysql4/Setup.php +0 -37
  75. app/code/core/Mage/GoogleCheckout/Model/Mysql4/Tax.php +0 -37
  76. app/code/core/Mage/GoogleCheckout/Model/Notification.php +0 -129
  77. app/code/core/Mage/GoogleCheckout/Model/Observer.php +0 -105
  78. app/code/core/Mage/GoogleCheckout/Model/Payment.php +31 -85
  79. app/code/core/Mage/GoogleCheckout/Model/Resource/Notification.php +0 -109
  80. app/code/core/Mage/GoogleCheckout/Model/Resource/Setup.php +0 -37
  81. app/code/core/Mage/GoogleCheckout/Model/Resource/Tax.php +0 -76
  82. app/code/core/Mage/GoogleCheckout/Model/Shipping.php +0 -76
  83. app/code/core/Mage/GoogleCheckout/Model/Source/Checkout/Image.php +0 -55
  84. app/code/core/Mage/GoogleCheckout/Model/Source/Locale.php +0 -37
  85. app/code/core/Mage/GoogleCheckout/Model/Source/Shipping/Carrier.php +0 -59
  86. app/code/core/Mage/GoogleCheckout/Model/Source/Shipping/Category.php +0 -37
  87. app/code/core/Mage/GoogleCheckout/Model/Source/Shipping/Units.php +0 -36
  88. app/code/core/Mage/GoogleCheckout/Model/Source/Shipping/Virtual/Method.php +0 -38
  89. app/code/core/Mage/GoogleCheckout/controllers/ApiController.php +0 -44
  90. app/code/core/Mage/GoogleCheckout/controllers/RedirectController.php +0 -181
  91. app/code/core/Mage/GoogleCheckout/etc/adminhtml.xml +0 -48
  92. app/code/core/Mage/GoogleCheckout/etc/config.xml +0 -136
  93. app/code/core/Mage/GoogleCheckout/etc/system.xml +0 -483
  94. app/code/core/Mage/GoogleCheckout/etc/wsdl.xml +0 -15
  95. app/code/core/Mage/GoogleCheckout/etc/wsi.xml +0 -18
  96. app/code/core/Mage/GoogleCheckout/sql/googlecheckout_setup/install-1.6.0.0.php +0 -83
  97. app/code/core/Mage/GoogleCheckout/sql/googlecheckout_setup/mysql4-upgrade-0.7.0-0.7.1.php +0 -64
  98. app/code/core/Mage/GoogleCheckout/sql/googlecheckout_setup/mysql4-upgrade-0.7.1-0.7.2.php +0 -46
  99. app/code/core/Mage/GoogleCheckout/sql/googlecheckout_setup/mysql4-upgrade-1.5.9.9-1.6.0.0.php +0 -62
  100. app/code/core/Mage/ImportExport/Model/Export/Entity/Product.php +0 -1
  101. app/code/core/Mage/ImportExport/Model/Import/Entity/Product.php +155 -6
  102. app/code/core/Mage/ImportExport/Model/Import/Entity/Product/Type/Abstract.php +19 -13
  103. app/code/core/Mage/ImportExport/Model/Import/Proxy/Product.php +10 -0
  104. app/code/core/Mage/Oauth/Model/Server.php +0 -2
  105. app/code/core/Mage/Page/Block/Html/Breadcrumbs.php +27 -2
  106. app/code/core/Mage/{GoogleCheckout/Block/Redirect.php → Page/Block/Html/CookieNotice.php} +17 -17
  107. app/code/core/Mage/Page/Block/Template/Links.php +19 -2
  108. app/code/core/Mage/Payment/Model/Method/Abstract.php +11 -0
  109. app/code/core/Mage/Payment/Model/Observer.php +50 -1
  110. app/code/core/Mage/Payment/etc/config.xml +10 -2
  111. app/code/core/Mage/Paypal/Model/Api/Nvp.php +43 -2
  112. app/code/core/Mage/Paypal/Model/Cart.php +15 -0
  113. app/code/core/Mage/Paypal/Model/Method/Agreement.php +4 -2
  114. app/code/core/Mage/Paypal/controllers/IpnController.php +1 -0
  115. app/code/core/Mage/{GoogleCheckout/Model/Resource/Api/Debug/Collection.php → PaypalUk/Model/Api/Express/Nvp.php} +13 -12
  116. app/code/core/Mage/PaypalUk/Model/Api/Nvp.php +53 -1
  117. app/code/core/Mage/PaypalUk/Model/Express.php +3 -2
  118. app/code/core/Mage/PaypalUk/Model/Express/Checkout.php +1 -1
  119. app/code/core/Mage/{GoogleCheckout/Model/Api/Xml/Calculate.php → PaypalUk/Model/Express/Pro.php} +9 -7
  120. app/code/core/Mage/Persistent/Model/Observer.php +2 -4
  121. app/code/core/Mage/Persistent/controllers/IndexController.php +1 -1
  122. app/code/core/Mage/Persistent/etc/config.xml +0 -8
  123. app/code/core/Mage/ProductAlert/Block/Email/Abstract.php +15 -0
  124. app/code/core/Mage/Reports/Model/Resource/Report/Abstract.php +33 -3
  125. app/code/core/Mage/Review/controllers/ProductController.php +6 -0
  126. app/code/core/Mage/Sales/Block/Guest/Links.php +2 -2
  127. app/code/core/Mage/Sales/Helper/Guest.php +4 -4
  128. app/code/core/Mage/Sales/Model/Order.php +26 -17
  129. app/code/core/Mage/Sales/Model/Order/Config.php +34 -3
  130. app/code/core/Mage/Sales/Model/Order/Creditmemo.php +15 -0
  131. app/code/core/Mage/Sales/Model/Order/Creditmemo/Total/Discount.php +3 -3
  132. app/code/core/Mage/Sales/Model/Order/Creditmemo/Total/Subtotal.php +2 -1
  133. app/code/core/Mage/Sales/Model/Order/Creditmemo/Total/Tax.php +19 -8
  134. app/code/core/Mage/Sales/Model/Order/Invoice/Total/Discount.php +12 -2
  135. app/code/core/Mage/Sales/Model/Order/Invoice/Total/Subtotal.php +7 -2
  136. app/code/core/Mage/Sales/Model/Order/Item.php +40 -0
  137. app/code/core/Mage/Sales/Model/Order/Payment.php +9 -2
  138. app/code/core/Mage/Sales/Model/Order/Shipment.php +2 -1
  139. app/code/core/Mage/Sales/Model/Order/Shipment/Track.php +10 -1
  140. app/code/core/Mage/Sales/Model/Quote/Item.php +41 -37
  141. app/code/core/Mage/Sales/Model/Quote/Item/Abstract.php +21 -5
  142. app/code/core/Mage/Sales/Model/Resource/Order/Status/Collection.php +14 -0
  143. app/code/core/Mage/Sales/etc/config.xml +0 -7
  144. app/code/core/Mage/Sales/etc/widget.xml +5 -0
  145. app/code/core/Mage/SalesRule/Model/Validator.php +138 -65
  146. app/code/core/Mage/Shipping/Model/Carrier/Tablerate.php +70 -16
  147. app/code/core/Mage/Tax/Block/Adminhtml/Notifications.php +36 -0
  148. app/code/core/Mage/Tax/Block/Checkout/Tax.php +6 -3
  149. app/code/core/Mage/Tax/Block/Sales/Order/Tax.php +13 -4
  150. app/code/core/Mage/Tax/Helper/Data.php +164 -66
  151. app/code/core/Mage/Tax/Model/Calculation.php +178 -33
  152. app/code/core/Mage/Tax/Model/Calculation/Rate.php +33 -2
  153. app/code/core/Mage/Tax/Model/Calculation/Rule.php +70 -1
  154. app/code/core/Mage/Tax/Model/Config.php +28 -19
  155. app/code/core/Mage/Tax/Model/Resource/Calculation/Rule.php +26 -0
  156. app/code/core/Mage/Tax/Model/Sales/Total/Quote/Shipping.php +24 -14
  157. app/code/core/Mage/Tax/Model/Sales/Total/Quote/Subtotal.php +337 -245
  158. app/code/core/Mage/Tax/Model/Sales/Total/Quote/Tax.php +796 -420
  159. app/code/core/Mage/Tax/Model/System/Config/Source/Tax/Region.php +26 -6
  160. app/code/core/Mage/Tax/etc/config.xml +1 -1
  161. app/code/core/Mage/Usa/Model/Shipping/Carrier/Dhl.php +0 -4
  162. app/code/core/Mage/Usa/Model/Shipping/Carrier/Dhl/International.php +0 -8
  163. app/code/core/Mage/Usa/Model/Shipping/Carrier/Dhl/Label/Pdf/Page.php +2 -2
  164. app/code/core/Mage/Usa/Model/Shipping/Carrier/Dhl/Label/Pdf/PageBuilder.php +6 -6
  165. app/code/core/Mage/Usa/Model/Shipping/Carrier/Fedex.php +8 -2
  166. app/code/core/Mage/Usa/Model/Shipping/Carrier/Usps.php +7 -7
  167. app/code/core/Mage/Weee/Block/Renderer/Weee/Tax.php +105 -20
  168. app/code/core/Mage/Weee/Helper/Data.php +292 -17
  169. app/code/core/Mage/{GoogleCheckout/Model/Source/Shipping/Virtual/Schedule.php → Weee/Model/Config/Source/Fpt/Tax.php} +24 -6
  170. app/code/core/Mage/Weee/Model/Observer.php +68 -25
  171. app/code/core/Mage/Weee/Model/Tax.php +75 -7
  172. app/code/core/Mage/Weee/Model/Total/Creditmemo/Weee.php +33 -8
  173. app/code/core/Mage/Weee/Model/Total/Invoice/Weee.php +13 -0
  174. app/code/core/Mage/Weee/Model/Total/Quote/Weee.php +135 -43
  175. app/code/core/Mage/Weee/etc/config.xml +18 -3
  176. app/code/core/Mage/Weee/etc/system.xml +2 -2
  177. app/code/core/Mage/Wishlist/Controller/Abstract.php +17 -4
  178. app/code/core/Mage/Wishlist/Helper/Data.php +1 -1
  179. cron.php +3 -0
  180. errors/design.xml +5 -5
  181. package.xml +5 -5
app/Mage.php CHANGED
@@ -39,6 +39,7 @@ if (defined('COMPILER_INCLUDE_PATH')) {
39
  /**
40
  * Set include path
41
  */
 
42
  $paths[] = BP . DS . 'app' . DS . 'code' . DS . 'local';
43
  $paths[] = BP . DS . 'app' . DS . 'code' . DS . 'community';
44
  $paths[] = BP . DS . 'app' . DS . 'code' . DS . 'core';
@@ -169,7 +170,7 @@ final class Mage
169
  return array(
170
  'major' => '1',
171
  'minor' => '8',
172
- 'revision' => '0',
173
  'patch' => '0',
174
  'stability' => '',
175
  'number' => '',
39
  /**
40
  * Set include path
41
  */
42
+ $paths = array();
43
  $paths[] = BP . DS . 'app' . DS . 'code' . DS . 'local';
44
  $paths[] = BP . DS . 'app' . DS . 'code' . DS . 'community';
45
  $paths[] = BP . DS . 'app' . DS . 'code' . DS . 'core';
170
  return array(
171
  'major' => '1',
172
  'minor' => '8',
173
+ 'revision' => '1',
174
  'patch' => '0',
175
  'stability' => '',
176
  'number' => '',
app/code/core/Mage/Api/Model/Server/Adapter/Soap.php CHANGED
@@ -208,12 +208,14 @@ class Mage_Api_Model_Server_Adapter_Soap
208
  ? $urlModel->getUrl('*/*/*', array('_current' => true, '_query' => $params))
209
  : $urlModel->getUrl('*/*/*');
210
 
211
- if( $withAuth ) {
212
  $phpAuthUser = $this->getController()->getRequest()->getServer('PHP_AUTH_USER', false);
213
  $phpAuthPw = $this->getController()->getRequest()->getServer('PHP_AUTH_PW', false);
 
214
 
215
  if ($phpAuthUser && $phpAuthPw) {
216
- $wsdlUrl = sprintf("http://%s:%s@%s", $phpAuthUser, $phpAuthPw, str_replace('http://', '', $wsdlUrl ));
 
217
  }
218
  }
219
 
208
  ? $urlModel->getUrl('*/*/*', array('_current' => true, '_query' => $params))
209
  : $urlModel->getUrl('*/*/*');
210
 
211
+ if ( $withAuth ) {
212
  $phpAuthUser = $this->getController()->getRequest()->getServer('PHP_AUTH_USER', false);
213
  $phpAuthPw = $this->getController()->getRequest()->getServer('PHP_AUTH_PW', false);
214
+ $scheme = $this->getController()->getRequest()->getScheme();
215
 
216
  if ($phpAuthUser && $phpAuthPw) {
217
+ $wsdlUrl = sprintf("%s://%s:%s@%s", $scheme, $phpAuthUser, $phpAuthPw,
218
+ str_replace($scheme . '://', '', $wsdlUrl));
219
  }
220
  }
221
 
app/code/core/Mage/Bundle/Block/Catalog/Product/View/Type/Bundle.php CHANGED
@@ -34,7 +34,18 @@
34
  */
35
  class Mage_Bundle_Block_Catalog_Product_View_Type_Bundle extends Mage_Catalog_Block_Product_View_Abstract
36
  {
 
 
 
 
 
37
  protected $_optionRenderers = array();
 
 
 
 
 
 
38
  protected $_options = null;
39
 
40
  /**
@@ -44,6 +55,18 @@ class Mage_Bundle_Block_Catalog_Product_View_Type_Bundle extends Mage_Catalog_Bl
44
  */
45
  protected $_mapRenderer = 'msrp_item';
46
 
 
 
 
 
 
 
 
 
 
 
 
 
47
  public function getOptions()
48
  {
49
  if (!$this->_options) {
@@ -66,6 +89,11 @@ class Mage_Bundle_Block_Catalog_Product_View_Type_Bundle extends Mage_Catalog_Bl
66
  return $this->_options;
67
  }
68
 
 
 
 
 
 
69
  public function hasOptions()
70
  {
71
  $this->getOptions();
@@ -92,7 +120,8 @@ class Mage_Bundle_Block_Catalog_Product_View_Type_Bundle extends Mage_Catalog_Bl
92
  /* @var $bundlePriceModel Mage_Bundle_Model_Product_Price */
93
  $bundlePriceModel = Mage::getModel('bundle/product_price');
94
 
95
- if ($preConfiguredFlag = $currentProduct->hasPreconfiguredValues()) {
 
96
  $preConfiguredValues = $currentProduct->getPreconfiguredValues();
97
  $defaultValues = array();
98
  }
@@ -122,9 +151,15 @@ class Mage_Bundle_Block_Catalog_Product_View_Type_Bundle extends Mage_Catalog_Bl
122
  // recalculate currency
123
  $tierPrices = $_selection->getTierPrice();
124
  foreach ($tierPrices as &$tierPriceInfo) {
 
 
 
 
125
  $tierPriceInfo['price'] = $coreHelper->currency($tierPriceInfo['price'], false, false);
126
- $tierPriceInfo['priceInclTax'] = $taxHelper->getPrice($_selection, $tierPriceInfo['price'], true);
127
- $tierPriceInfo['priceExclTax'] = $taxHelper->getPrice($_selection, $tierPriceInfo['price']);
 
 
128
  }
129
  unset($tierPriceInfo); // break the reference with the last element
130
 
@@ -137,12 +172,16 @@ class Mage_Bundle_Block_Catalog_Product_View_Type_Bundle extends Mage_Catalog_Bl
137
  /* @var $taxHelper Mage_Tax_Helper_Data */
138
  $taxHelper = Mage::helper('tax');
139
 
140
- $_priceInclTax = $taxHelper->getPrice($_selection, $itemPrice, true);
141
- $_priceExclTax = $taxHelper->getPrice($_selection, $itemPrice);
 
 
142
 
143
  if ($currentProduct->getPriceType() == Mage_Bundle_Model_Product_Price::PRICE_TYPE_FIXED) {
144
- $_priceInclTax = $taxHelper->getPrice($currentProduct, $itemPrice, true);
145
- $_priceExclTax = $taxHelper->getPrice($currentProduct, $itemPrice);
 
 
146
  }
147
 
148
  $selection = array (
@@ -158,7 +197,7 @@ class Mage_Bundle_Block_Catalog_Product_View_Type_Bundle extends Mage_Catalog_Bl
158
  'plusDisposition' => 0,
159
  'minusDisposition' => 0,
160
  'canApplyMAP' => $canApplyMAP,
161
- 'tierPriceHtml' => $this->getTierPriceHtml($_selection),
162
  );
163
 
164
  $responseObject = new Varien_Object();
@@ -208,11 +247,23 @@ class Mage_Bundle_Block_Catalog_Product_View_Type_Bundle extends Mage_Catalog_Bl
208
  return $coreHelper->jsonEncode($config);
209
  }
210
 
 
 
 
 
 
 
211
  public function addRenderer($type, $block)
212
  {
213
  $this->_optionRenderers[$type] = $block;
214
  }
215
 
 
 
 
 
 
 
216
  public function getOptionHtml($option)
217
  {
218
  if (!isset($this->_optionRenderers[$option->getType()])) {
34
  */
35
  class Mage_Bundle_Block_Catalog_Product_View_Type_Bundle extends Mage_Catalog_Block_Product_View_Abstract
36
  {
37
+ /**
38
+ * Renderers for bundle product options
39
+ *
40
+ * @var array
41
+ */
42
  protected $_optionRenderers = array();
43
+
44
+ /**
45
+ * Bundle product options
46
+ *
47
+ * @var array
48
+ */
49
  protected $_options = null;
50
 
51
  /**
55
  */
56
  protected $_mapRenderer = 'msrp_item';
57
 
58
+ /**
59
+ * Tier price template
60
+ *
61
+ * @var string
62
+ */
63
+ protected $_tierPriceDefaultTemplate = 'bundle/catalog/product/view/option_tierprices.phtml';
64
+
65
+ /**
66
+ * Return an array of bundle product options
67
+ *
68
+ * @return array
69
+ */
70
  public function getOptions()
71
  {
72
  if (!$this->_options) {
89
  return $this->_options;
90
  }
91
 
92
+ /**
93
+ * Whether the bundle product has any option
94
+ *
95
+ * @return boolean
96
+ */
97
  public function hasOptions()
98
  {
99
  $this->getOptions();
120
  /* @var $bundlePriceModel Mage_Bundle_Model_Product_Price */
121
  $bundlePriceModel = Mage::getModel('bundle/product_price');
122
 
123
+ $preConfiguredFlag = $currentProduct->hasPreconfiguredValues();
124
+ if ($preConfiguredFlag) {
125
  $preConfiguredValues = $currentProduct->getPreconfiguredValues();
126
  $defaultValues = array();
127
  }
151
  // recalculate currency
152
  $tierPrices = $_selection->getTierPrice();
153
  foreach ($tierPrices as &$tierPriceInfo) {
154
+ $tierPriceInfo['price'] =
155
+ $bundlePriceModel->getLowestPrice($currentProduct, $tierPriceInfo['price']);
156
+ $tierPriceInfo['website_price'] =
157
+ $bundlePriceModel->getLowestPrice($currentProduct, $tierPriceInfo['website_price']);
158
  $tierPriceInfo['price'] = $coreHelper->currency($tierPriceInfo['price'], false, false);
159
+ $tierPriceInfo['priceInclTax'] = $taxHelper->getPrice($_selection, $tierPriceInfo['price'], true,
160
+ null, null, null, null, null, false);
161
+ $tierPriceInfo['priceExclTax'] = $taxHelper->getPrice($_selection, $tierPriceInfo['price'], false,
162
+ null, null, null, null, null, false);
163
  }
164
  unset($tierPriceInfo); // break the reference with the last element
165
 
172
  /* @var $taxHelper Mage_Tax_Helper_Data */
173
  $taxHelper = Mage::helper('tax');
174
 
175
+ $_priceInclTax = $taxHelper->getPrice($_selection, $itemPrice, true,
176
+ null, null, null, null, null, false);
177
+ $_priceExclTax = $taxHelper->getPrice($_selection, $itemPrice, false,
178
+ null, null, null, null, null, false);
179
 
180
  if ($currentProduct->getPriceType() == Mage_Bundle_Model_Product_Price::PRICE_TYPE_FIXED) {
181
+ $_priceInclTax = $taxHelper->getPrice($currentProduct, $itemPrice, true,
182
+ null, null, null, null, null, false);
183
+ $_priceExclTax = $taxHelper->getPrice($currentProduct, $itemPrice, false,
184
+ null, null, null, null, null, false);
185
  }
186
 
187
  $selection = array (
197
  'plusDisposition' => 0,
198
  'minusDisposition' => 0,
199
  'canApplyMAP' => $canApplyMAP,
200
+ 'tierPriceHtml' => $this->getTierPriceHtml($_selection, $currentProduct),
201
  );
202
 
203
  $responseObject = new Varien_Object();
247
  return $coreHelper->jsonEncode($config);
248
  }
249
 
250
+ /**
251
+ * Add renderer for an option type, e.g., select, radio button, etc.
252
+ *
253
+ * @param string $type
254
+ * @param string $block
255
+ */
256
  public function addRenderer($type, $block)
257
  {
258
  $this->_optionRenderers[$type] = $block;
259
  }
260
 
261
+ /**
262
+ * Get option html
263
+ *
264
+ * @param Mage_Catalog_Model_Product_Option $option
265
+ * @return string
266
+ */
267
  public function getOptionHtml($option)
268
  {
269
  if (!isset($this->_optionRenderers[$option->getType()])) {
app/code/core/Mage/Bundle/Block/Catalog/Product/View/Type/Bundle/Option.php CHANGED
@@ -81,17 +81,17 @@ class Mage_Bundle_Block_Catalog_Product_View_Type_Bundle_Option extends Mage_Bun
81
  ->getData('bundle_option_qty/' . $_option->getId());
82
 
83
  if (empty($selectedOptions) && $_default) {
84
- $_defaultQty = $_default->getSelectionQty()*1;
85
  $_canChangeQty = $_default->getSelectionCanChangeQty();
86
  } elseif (!$inPreConfigured && $selectedOptions && is_numeric($selectedOptions)) {
87
  $selectedSelection = $_option->getSelectionById($selectedOptions);
88
- $_defaultQty = $selectedSelection->getSelectionQty()*1;
89
  $_canChangeQty = $selectedSelection->getSelectionCanChangeQty();
90
  } elseif (!$this->_showSingle() || $inPreConfigured) {
91
  $_defaultQty = $this->_getSelectedQty();
92
  $_canChangeQty = (bool)$_defaultQty;
93
  } else {
94
- $_defaultQty = $_selections[0]->getSelectionQty()*1;
95
  $_canChangeQty = $_selections[0]->getSelectionCanChangeQty();
96
  }
97
 
@@ -176,17 +176,24 @@ class Mage_Bundle_Block_Catalog_Product_View_Type_Bundle_Option extends Mage_Bun
176
  return $this->getData('product');
177
  }
178
 
 
 
 
 
 
 
 
179
  public function getSelectionQtyTitlePrice($_selection, $includeContainer = true)
180
  {
181
  $price = $this->getProduct()->getPriceModel()->getSelectionPreFinalPrice($this->getProduct(), $_selection);
182
  $this->setFormatProduct($_selection);
183
- $priceTitle = $_selection->getSelectionQty()*1 . ' x ' . $this->escapeHtml($_selection->getName());
184
 
185
  $priceTitle .= ' &nbsp; ' . ($includeContainer ? '<span class="price-notice">' : '')
186
  . '+' . $this->formatPriceString($price, $includeContainer)
187
  . ($includeContainer ? '</span>' : '');
188
 
189
- return $priceTitle;
190
  }
191
 
192
  /**
@@ -218,11 +225,6 @@ class Mage_Bundle_Block_Catalog_Product_View_Type_Bundle_Option extends Mage_Bun
218
  public function getSelectionTitlePrice($_selection, $includeContainer = true)
219
  {
220
  $price = $this->getProduct()->getPriceModel()->getSelectionPreFinalPrice($this->getProduct(), $_selection, 1);
221
- $tierPrice = $_selection->getTierPrice();
222
- if (!empty($tierPrice)) {
223
- $qty = $_selection->getSelectionQty();
224
- $price = $qty * (float) $_selection->getPriceModel()->getTierPrice($qty, $_selection);
225
- }
226
  $this->setFormatProduct($_selection);
227
  $priceTitle = $this->escapeHtml($_selection->getName());
228
  $priceTitle .= ' &nbsp; ' . ($includeContainer ? '<span class="price-notice">' : '')
81
  ->getData('bundle_option_qty/' . $_option->getId());
82
 
83
  if (empty($selectedOptions) && $_default) {
84
+ $_defaultQty = $_default->getSelectionQty() * 1;
85
  $_canChangeQty = $_default->getSelectionCanChangeQty();
86
  } elseif (!$inPreConfigured && $selectedOptions && is_numeric($selectedOptions)) {
87
  $selectedSelection = $_option->getSelectionById($selectedOptions);
88
+ $_defaultQty = $selectedSelection->getSelectionQty() * 1;
89
  $_canChangeQty = $selectedSelection->getSelectionCanChangeQty();
90
  } elseif (!$this->_showSingle() || $inPreConfigured) {
91
  $_defaultQty = $this->_getSelectedQty();
92
  $_canChangeQty = (bool)$_defaultQty;
93
  } else {
94
+ $_defaultQty = $_selections[0]->getSelectionQty() * 1;
95
  $_canChangeQty = $_selections[0]->getSelectionCanChangeQty();
96
  }
97
 
176
  return $this->getData('product');
177
  }
178
 
179
+ /**
180
+ * Returns the formatted string for the quantity chosen for the given selection
181
+ *
182
+ * @param Mage_Catalog_Model_Proudct $_selection
183
+ * @param bool $includeContainer
184
+ * @return string
185
+ */
186
  public function getSelectionQtyTitlePrice($_selection, $includeContainer = true)
187
  {
188
  $price = $this->getProduct()->getPriceModel()->getSelectionPreFinalPrice($this->getProduct(), $_selection);
189
  $this->setFormatProduct($_selection);
190
+ $priceTitle = $_selection->getSelectionQty() * 1 . ' x ' . $this->escapeHtml($_selection->getName());
191
 
192
  $priceTitle .= ' &nbsp; ' . ($includeContainer ? '<span class="price-notice">' : '')
193
  . '+' . $this->formatPriceString($price, $includeContainer)
194
  . ($includeContainer ? '</span>' : '');
195
 
196
+ return $priceTitle;
197
  }
198
 
199
  /**
225
  public function getSelectionTitlePrice($_selection, $includeContainer = true)
226
  {
227
  $price = $this->getProduct()->getPriceModel()->getSelectionPreFinalPrice($this->getProduct(), $_selection, 1);
 
 
 
 
 
228
  $this->setFormatProduct($_selection);
229
  $priceTitle = $this->escapeHtml($_selection->getName());
230
  $priceTitle .= ' &nbsp; ' . ($includeContainer ? '<span class="price-notice">' : '')
app/code/core/Mage/Bundle/Model/Product/Price.php CHANGED
@@ -36,12 +36,12 @@ class Mage_Bundle_Model_Product_Price extends Mage_Catalog_Model_Product_Type_Pr
36
  /**
37
  * Fixed price type
38
  */
39
- const PRICE_TYPE_FIXED = 1;
40
 
41
  /**
42
  * Dynamic price type
43
  */
44
- const PRICE_TYPE_DYNAMIC = 0;
45
 
46
  /**
47
  * Flag which indicates - is min/max prices have been calculated by index
@@ -112,7 +112,7 @@ class Mage_Bundle_Model_Product_Price extends Mage_Catalog_Model_Product_Type_Pr
112
  /**
113
  * Get product final price
114
  *
115
- * @param double $qty
116
  * @param Mage_Catalog_Model_Product $product
117
  * @return double
118
  */
@@ -138,9 +138,9 @@ class Mage_Bundle_Model_Product_Price extends Mage_Catalog_Model_Product_Type_Pr
138
  * Returns final price of a child product
139
  *
140
  * @param Mage_Catalog_Model_Product $product
141
- * @param float $productQty
142
  * @param Mage_Catalog_Model_Product $childProduct
143
- * @param float $childProductQty
144
  * @return decimal
145
  */
146
  public function getChildFinalPrice($product, $productQty, $childProduct, $childProductQty)
@@ -155,7 +155,7 @@ class Mage_Bundle_Model_Product_Price extends Mage_Catalog_Model_Product_Type_Pr
155
  * @see Mage_Bundle_Model_Product_Price::getTotalPrices()
156
  *
157
  * @param Mage_Catalog_Model_Product $product
158
- * @param string $which
159
  * @return decimal|array
160
  */
161
  public function getPrices($product, $which = null)
@@ -170,8 +170,8 @@ class Mage_Bundle_Model_Product_Price extends Mage_Catalog_Model_Product_Type_Pr
170
  * @see Mage_Bundle_Model_Product_Price::getTotalPrices()
171
  *
172
  * @param Mage_Catalog_Model_Product $product
173
- * @param string $which
174
- * @param bool|null $includeTax
175
  * @return decimal|array
176
  */
177
  public function getPricesDependingOnTax($product, $which = null, $includeTax = null)
@@ -183,9 +183,9 @@ class Mage_Bundle_Model_Product_Price extends Mage_Catalog_Model_Product_Type_Pr
183
  * Retrieve Price considering tier price
184
  *
185
  * @param Mage_Catalog_Model_Product $product
186
- * @param string|null $which
187
- * @param bool|null $includeTax
188
- * @param bool $takeTierPrice
189
  * @return decimal|array
190
  */
191
  public function getTotalPrices($product, $which = null, $includeTax = null, $takeTierPrice = true)
@@ -195,15 +195,18 @@ class Mage_Bundle_Model_Product_Price extends Mage_Catalog_Model_Product_Type_Pr
195
  $taxHelper = $this->_getHelperData('tax');
196
 
197
  if ($this->_isPricesCalculatedByIndex && !$includeTax) {
198
- $minimalPrice = $taxHelper->getPrice($product, $product->getData('min_price'), $includeTax);
199
- $maximalPrice = $taxHelper->getPrice($product, $product->getData('max_price'), $includeTax);
 
 
200
  } else {
201
  /**
202
  * Check if product price is fixed
203
  */
204
  $finalPrice = $product->getFinalPrice();
205
  if ($isPriceFixedType) {
206
- $minimalPrice = $maximalPrice = $taxHelper->getPrice($product, $finalPrice, $includeTax);
 
207
  } else { // PRICE_TYPE_DYNAMIC
208
  $minimalPrice = $maximalPrice = 0;
209
  }
@@ -227,6 +230,9 @@ class Mage_Bundle_Model_Product_Price extends Mage_Catalog_Model_Product_Type_Pr
227
  }
228
  }
229
 
 
 
 
230
  if ('max' == $which) {
231
  return $maximalPrice;
232
  } elseif ('min' == $which) {
@@ -248,8 +254,10 @@ class Mage_Bundle_Model_Product_Price extends Mage_Catalog_Model_Product_Type_Pr
248
  {
249
  $options = $this->getOptions($product);
250
  $minimalPrice = 0;
 
251
  $hasRequiredOptions = $this->_hasRequiredOptions($product);
252
  $selectionMinimalPrices = array();
 
253
 
254
  if (!$options) {
255
  return $minimalPrice;
@@ -257,20 +265,41 @@ class Mage_Bundle_Model_Product_Price extends Mage_Catalog_Model_Product_Type_Pr
257
 
258
  foreach ($options as $option) {
259
  /* @var $option Mage_Bundle_Model_Option */
260
- $selectionPrices = $this->_getSelectionPrices($product, $option, $takeTierPrice, $includeTax);
 
261
 
262
  if (count($selectionPrices)) {
263
- $selectionMinPrice = min($selectionPrices);
 
 
264
  if ($option->getRequired()) {
265
  $minimalPrice += $selectionMinPrice;
 
266
  } elseif (!$hasRequiredOptions) {
267
  $selectionMinimalPrices[] = $selectionMinPrice;
 
268
  }
269
  }
270
  }
271
  // condition is TRUE when all product options are NOT required
272
  if (!$hasRequiredOptions) {
273
  $minimalPrice = min($selectionMinimalPrices);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
274
  }
275
  return $minimalPrice;
276
  }
@@ -316,6 +345,7 @@ class Mage_Bundle_Model_Product_Price extends Mage_Catalog_Model_Product_Type_Pr
316
  {
317
  $selectionPrices = array();
318
  $taxHelper = $this->_getHelperData('tax');
 
319
  $isPriceFixedType = ($product->getPriceType() == self::PRICE_TYPE_FIXED);
320
 
321
  $selections = $option->getSelections();
@@ -334,11 +364,20 @@ class Mage_Bundle_Model_Product_Price extends Mage_Catalog_Model_Product_Type_Pr
334
 
335
  $item = $isPriceFixedType ? $product : $selection;
336
 
337
- $selectionPrices[] = $taxHelper->getPrice(
338
- $item,
339
- $this->getSelectionFinalTotalPrice($product, $selection, 1, null, true, $takeTierPrice),
340
- $includeTax
341
- );
 
 
 
 
 
 
 
 
 
342
  }
343
  return $selectionPrices;
344
  }
@@ -396,8 +435,8 @@ class Mage_Bundle_Model_Product_Price extends Mage_Catalog_Model_Product_Type_Pr
396
  *
397
  * @param Mage_Catalog_Model_Product $bundleProduct
398
  * @param Mage_Catalog_Model_Product $selectionProduct
399
- * @param float|null $selectionQty
400
- * @param null|bool $multiplyQty Whether to multiply selection's price by its quantity
401
  * @return float
402
  */
403
  public function getSelectionPrice($bundleProduct, $selectionProduct, $selectionQty = null, $multiplyQty = true)
@@ -410,7 +449,7 @@ class Mage_Bundle_Model_Product_Price extends Mage_Catalog_Model_Product_Type_Pr
410
  *
411
  * @param Mage_Catalog_Model_Product $bundleProduct
412
  * @param Mage_Catalog_Model_Product $selectionProduct
413
- * @param decimal $qty
414
  * @return decimal
415
  */
416
  public function getSelectionPreFinalPrice($bundleProduct, $selectionProduct, $qty = null)
@@ -426,13 +465,13 @@ class Mage_Bundle_Model_Product_Price extends Mage_Catalog_Model_Product_Type_Pr
426
  *
427
  * @param Mage_Catalog_Model_Product $bundleProduct
428
  * @param Mage_Catalog_Model_Product $selectionProduct
429
- * @param decimal $bundleQty
430
- * @param decimal $selectionQty
431
- * @param bool $multiplyQty
432
  * @return decimal
433
  */
434
  public function getSelectionFinalPrice($bundleProduct, $selectionProduct, $bundleQty, $selectionQty = null,
435
- $multiplyQty = true)
436
  {
437
  return $this->getSelectionFinalTotalPrice($bundleProduct, $selectionProduct, $bundleQty, $selectionQty,
438
  $multiplyQty);
@@ -444,14 +483,14 @@ class Mage_Bundle_Model_Product_Price extends Mage_Catalog_Model_Product_Type_Pr
444
  *
445
  * @param Mage_Catalog_Model_Product $bundleProduct
446
  * @param Mage_Catalog_Model_Product $selectionProduct
447
- * @param decimal $bundleQty
448
- * @param decimal $selectionQty
449
- * @param bool $multiplyQty
450
- * @param bool $takeTierPrice
451
- * @return decimal
452
  */
453
  public function getSelectionFinalTotalPrice($bundleProduct, $selectionProduct, $bundleQty, $selectionQty,
454
- $multiplyQty = true, $takeTierPrice = true)
455
  {
456
  if (is_null($selectionQty)) {
457
  $selectionQty = $selectionProduct->getSelectionQty();
@@ -474,11 +513,7 @@ class Mage_Bundle_Model_Product_Price extends Mage_Catalog_Model_Product_Type_Pr
474
  }
475
  }
476
 
477
- $price = min($price,
478
- $this->_applyGroupPrice($bundleProduct, $price),
479
- $this->_applyTierPrice($bundleProduct, $bundleQty, $price),
480
- $this->_applySpecialPrice($bundleProduct, $price)
481
- );
482
 
483
  if ($multiplyQty) {
484
  $price *= $selectionQty;
@@ -487,6 +522,24 @@ class Mage_Bundle_Model_Product_Price extends Mage_Catalog_Model_Product_Type_Pr
487
  return $price;
488
  }
489
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
490
  /**
491
  * Apply group price for bundle product
492
  *
@@ -501,6 +554,7 @@ class Mage_Bundle_Model_Product_Price extends Mage_Catalog_Model_Product_Type_Pr
501
 
502
  if (is_numeric($groupPrice)) {
503
  $groupPrice = $finalPrice - ($finalPrice * ($groupPrice / 100));
 
504
  $result = min($finalPrice, $groupPrice);
505
  }
506
 
@@ -547,8 +601,8 @@ class Mage_Bundle_Model_Product_Price extends Mage_Catalog_Model_Product_Type_Pr
547
  * Apply tier price for bundle
548
  *
549
  * @param Mage_Catalog_Model_Product $product
550
- * @param decimal $qty
551
- * @param decimal $finalPrice
552
  * @return decimal
553
  */
554
  protected function _applyTierPrice($product, $qty, $finalPrice)
@@ -557,10 +611,11 @@ class Mage_Bundle_Model_Product_Price extends Mage_Catalog_Model_Product_Type_Pr
557
  return $finalPrice;
558
  }
559
 
560
- $tierPrice = $product->getTierPrice($qty);
561
 
562
  if (is_numeric($tierPrice)) {
563
  $tierPrice = $finalPrice - ($finalPrice * ($tierPrice / 100));
 
564
  $finalPrice = min($finalPrice, $tierPrice);
565
  }
566
 
@@ -570,7 +625,7 @@ class Mage_Bundle_Model_Product_Price extends Mage_Catalog_Model_Product_Type_Pr
570
  /**
571
  * Get product tier price by qty
572
  *
573
- * @param decimal $qty
574
  * @param Mage_Catalog_Model_Product $product
575
  * @return decimal
576
  */
@@ -589,13 +644,13 @@ class Mage_Bundle_Model_Product_Price extends Mage_Catalog_Model_Product_Type_Pr
589
 
590
  if (is_null($prices) || !is_array($prices)) {
591
  if (!is_null($qty)) {
592
- return $product->getPrice();
593
  }
594
  return array(array(
595
- 'price' => $product->getPrice(),
596
- 'website_price' => $product->getPrice(),
597
- 'price_qty' => 1,
598
- 'cust_group' => $allGroups
599
  ));
600
  }
601
 
@@ -624,9 +679,9 @@ class Mage_Bundle_Model_Product_Price extends Mage_Catalog_Model_Product_Type_Pr
624
  }
625
 
626
  if ($price['website_price'] > $prevPrice) {
627
- $prevPrice = $price['website_price'];
628
- $prevQty = $price['price_qty'];
629
- $prevGroup = $price['cust_group'];
630
  }
631
  }
632
 
@@ -656,18 +711,18 @@ class Mage_Bundle_Model_Product_Price extends Mage_Catalog_Model_Product_Type_Pr
656
  /**
657
  * Calculate product price based on special price data and price rules
658
  *
659
- * @param float $basePrice
660
- * @param float $specialPrice
661
- * @param string $specialPriceFrom
662
- * @param string $specialPriceTo
663
  * @param float|null|false $rulePrice
664
- * @param mixed $wId
665
- * @param mixed $gId
666
- * @param null|int $productId
667
  * @return float
668
  */
669
  public static function calculatePrice($basePrice, $specialPrice, $specialPriceFrom, $specialPriceTo,
670
- $rulePrice = false, $wId = null, $gId = null, $productId = null)
671
  {
672
  $resource = Mage::getResourceSingleton('bundle/bundle');
673
  $selectionResource = Mage::getResourceSingleton('bundle/selection');
@@ -717,7 +772,7 @@ class Mage_Bundle_Model_Product_Price extends Mage_Catalog_Model_Product_Type_Pr
717
  $result['final_price'] = $selectionResource->getPriceFromIndex($result['product_id'], $qty, $store,
718
  $gId);
719
 
720
- $selectionPrice = $result['final_price']*$qty;
721
 
722
  if (isset($options[$result['option_id']])) {
723
  $options[$result['option_id']] = min($options[$result['option_id']], $selectionPrice);
@@ -732,7 +787,7 @@ class Mage_Bundle_Model_Product_Price extends Mage_Catalog_Model_Product_Type_Pr
732
  continue;
733
  }
734
  if ($result['selection_price_type']) {
735
- $selectionPrice = $basePrice*$result['selection_price_value']/100;
736
  } else {
737
  $selectionPrice = $result['selection_price_value'];
738
  }
@@ -745,7 +800,7 @@ class Mage_Bundle_Model_Product_Price extends Mage_Catalog_Model_Product_Type_Pr
745
  $qty = $result['selection_qty'];
746
  }
747
 
748
- $selectionPrice = $selectionPrice*$qty;
749
 
750
  if (isset($options[$result['option_id']])) {
751
  $options[$result['option_id']] = min($options[$result['option_id']], $selectionPrice);
@@ -801,20 +856,20 @@ class Mage_Bundle_Model_Product_Price extends Mage_Catalog_Model_Product_Type_Pr
801
  /**
802
  * Calculate and apply special price
803
  *
804
- * @param float $finalPrice
805
- * @param float $specialPrice
806
  * @param string $specialPriceFrom
807
  * @param string $specialPriceTo
808
- * @param mixed $store
809
  * @return float
810
  */
811
  public static function calculateSpecialPrice($finalPrice, $specialPrice, $specialPriceFrom, $specialPriceTo,
812
- $store = null)
813
  {
814
  if (!is_null($specialPrice) && $specialPrice != false) {
815
  if (Mage::app()->getLocale()->isStoreDateInInterval($store, $specialPriceFrom, $specialPriceTo)) {
816
- $specialPrice = Mage::app()->getStore()->roundPrice($finalPrice * $specialPrice / 100);
817
- $finalPrice = min($finalPrice, $specialPrice);
818
  }
819
  }
820
 
@@ -842,6 +897,16 @@ class Mage_Bundle_Model_Product_Price extends Mage_Catalog_Model_Product_Type_Pr
842
  return Mage::helper($name);
843
  }
844
 
 
 
 
 
 
 
 
 
 
 
845
  /**
846
  * Check if product has required options
847
  *
36
  /**
37
  * Fixed price type
38
  */
39
+ const PRICE_TYPE_FIXED = 1;
40
 
41
  /**
42
  * Dynamic price type
43
  */
44
+ const PRICE_TYPE_DYNAMIC = 0;
45
 
46
  /**
47
  * Flag which indicates - is min/max prices have been calculated by index
112
  /**
113
  * Get product final price
114
  *
115
+ * @param double $qty
116
  * @param Mage_Catalog_Model_Product $product
117
  * @return double
118
  */
138
  * Returns final price of a child product
139
  *
140
  * @param Mage_Catalog_Model_Product $product
141
+ * @param float $productQty
142
  * @param Mage_Catalog_Model_Product $childProduct
143
+ * @param float $childProductQty
144
  * @return decimal
145
  */
146
  public function getChildFinalPrice($product, $productQty, $childProduct, $childProductQty)
155
  * @see Mage_Bundle_Model_Product_Price::getTotalPrices()
156
  *
157
  * @param Mage_Catalog_Model_Product $product
158
+ * @param string $which
159
  * @return decimal|array
160
  */
161
  public function getPrices($product, $which = null)
170
  * @see Mage_Bundle_Model_Product_Price::getTotalPrices()
171
  *
172
  * @param Mage_Catalog_Model_Product $product
173
+ * @param string $which
174
+ * @param bool|null $includeTax
175
  * @return decimal|array
176
  */
177
  public function getPricesDependingOnTax($product, $which = null, $includeTax = null)
183
  * Retrieve Price considering tier price
184
  *
185
  * @param Mage_Catalog_Model_Product $product
186
+ * @param string|null $which
187
+ * @param bool|null $includeTax
188
+ * @param bool $takeTierPrice
189
  * @return decimal|array
190
  */
191
  public function getTotalPrices($product, $which = null, $includeTax = null, $takeTierPrice = true)
195
  $taxHelper = $this->_getHelperData('tax');
196
 
197
  if ($this->_isPricesCalculatedByIndex && !$includeTax) {
198
+ $minimalPrice = $taxHelper->getPrice($product, $product->getData('min_price'), $includeTax,
199
+ null, null, null, null, null, false);
200
+ $maximalPrice = $taxHelper->getPrice($product, $product->getData('max_price'), $includeTax,
201
+ null, null, null, null, null, false);
202
  } else {
203
  /**
204
  * Check if product price is fixed
205
  */
206
  $finalPrice = $product->getFinalPrice();
207
  if ($isPriceFixedType) {
208
+ $minimalPrice = $maximalPrice = $taxHelper->getPrice($product, $finalPrice, $includeTax,
209
+ null, null, null, null, null, false);
210
  } else { // PRICE_TYPE_DYNAMIC
211
  $minimalPrice = $maximalPrice = 0;
212
  }
230
  }
231
  }
232
 
233
+ $minimalPrice = $product->getStore()->roundPrice($minimalPrice);
234
+ $maximalPrice = $product->getStore()->roundPrice($maximalPrice);
235
+
236
  if ('max' == $which) {
237
  return $maximalPrice;
238
  } elseif ('min' == $which) {
254
  {
255
  $options = $this->getOptions($product);
256
  $minimalPrice = 0;
257
+ $minimalPriceWithTax = 0;
258
  $hasRequiredOptions = $this->_hasRequiredOptions($product);
259
  $selectionMinimalPrices = array();
260
+ $selectionMinimalPricesWithTax = array();
261
 
262
  if (!$options) {
263
  return $minimalPrice;
265
 
266
  foreach ($options as $option) {
267
  /* @var $option Mage_Bundle_Model_Option */
268
+ $selectionPrices = $this->_getSelectionPrices($product, $option, $takeTierPrice, $includeTax);
269
+ $selectionPricesWithTax = $this->_getSelectionPrices($product, $option, $takeTierPrice, true);
270
 
271
  if (count($selectionPrices)) {
272
+ $selectionMinPrice = is_array($selectionPrices) ? min($selectionPrices) : $selectionPrices;
273
+ $selectMinPriceWithTax = is_array($selectionPricesWithTax) ?
274
+ min($selectionPricesWithTax) : $selectionPricesWithTax;
275
  if ($option->getRequired()) {
276
  $minimalPrice += $selectionMinPrice;
277
+ $minimalPriceWithTax += $selectMinPriceWithTax;
278
  } elseif (!$hasRequiredOptions) {
279
  $selectionMinimalPrices[] = $selectionMinPrice;
280
+ $selectionMinimalPricesWithTax[] = $selectMinPriceWithTax;
281
  }
282
  }
283
  }
284
  // condition is TRUE when all product options are NOT required
285
  if (!$hasRequiredOptions) {
286
  $minimalPrice = min($selectionMinimalPrices);
287
+ $minimalPriceWithTax = min($selectionMinimalPricesWithTax);
288
+ }
289
+
290
+ $taxConfig = $this->_getHelperData('tax')->getConfig();
291
+
292
+ //In the case of total base calculation we round the tax first and
293
+ //deduct the tax from the price including tax
294
+ if ($taxConfig->priceIncludesTax($product->getStore())
295
+ && Mage_Tax_Model_Calculation::CALC_TOTAL_BASE ==
296
+ $taxConfig->getAlgorithm($product->getStore())
297
+ && ($minimalPriceWithTax > $minimalPrice)
298
+ ) {
299
+ //We convert the value to string to maintain the precision
300
+ $tax = (String)($minimalPriceWithTax - $minimalPrice);
301
+ $roundedTax = $this->_getApp()->getStore()->roundPrice($tax);
302
+ $minimalPrice = $minimalPriceWithTax - $roundedTax;
303
  }
304
  return $minimalPrice;
305
  }
345
  {
346
  $selectionPrices = array();
347
  $taxHelper = $this->_getHelperData('tax');
348
+ $taxCalcMethod = $taxHelper->getConfig()->getAlgorithm($product->getStore());
349
  $isPriceFixedType = ($product->getPriceType() == self::PRICE_TYPE_FIXED);
350
 
351
  $selections = $option->getSelections();
364
 
365
  $item = $isPriceFixedType ? $product : $selection;
366
 
367
+ $selectionUnitPrice = $this->getSelectionFinalTotalPrice(
368
+ $product, $selection, 1, null, false, $takeTierPrice);
369
+ $selectionQty = $selection->getSelectionQty();
370
+ if ($isPriceFixedType || $taxCalcMethod == Mage_Tax_Model_Calculation::CALC_TOTAL_BASE) {
371
+ $selectionPrice = $selectionQty * $taxHelper->getPrice($item, $selectionUnitPrice, $includeTax,
372
+ null, null, null, null, null, false);
373
+ $selectionPrices[] = $selectionPrice;
374
+ } else if ($taxCalcMethod == Mage_Tax_Model_Calculation::CALC_ROW_BASE) {
375
+ $selectionPrice = $taxHelper->getPrice($item, $selectionUnitPrice * $selectionQty, $includeTax);
376
+ $selectionPrices[] = $selectionPrice;
377
+ } else { //dynamic price and Mage_Tax_Model_Calculation::CALC_UNIT_BASE
378
+ $selectionPrice = $taxHelper->getPrice($item, $selectionUnitPrice, $includeTax) * $selectionQty;
379
+ $selectionPrices[] = $selectionPrice;
380
+ }
381
  }
382
  return $selectionPrices;
383
  }
435
  *
436
  * @param Mage_Catalog_Model_Product $bundleProduct
437
  * @param Mage_Catalog_Model_Product $selectionProduct
438
+ * @param float|null $selectionQty
439
+ * @param null|bool $multiplyQty Whether to multiply selection's price by its quantity
440
  * @return float
441
  */
442
  public function getSelectionPrice($bundleProduct, $selectionProduct, $selectionQty = null, $multiplyQty = true)
449
  *
450
  * @param Mage_Catalog_Model_Product $bundleProduct
451
  * @param Mage_Catalog_Model_Product $selectionProduct
452
+ * @param decimal $qty
453
  * @return decimal
454
  */
455
  public function getSelectionPreFinalPrice($bundleProduct, $selectionProduct, $qty = null)
465
  *
466
  * @param Mage_Catalog_Model_Product $bundleProduct
467
  * @param Mage_Catalog_Model_Product $selectionProduct
468
+ * @param decimal $bundleQty
469
+ * @param decimal $selectionQty
470
+ * @param bool $multiplyQty
471
  * @return decimal
472
  */
473
  public function getSelectionFinalPrice($bundleProduct, $selectionProduct, $bundleQty, $selectionQty = null,
474
+ $multiplyQty = true)
475
  {
476
  return $this->getSelectionFinalTotalPrice($bundleProduct, $selectionProduct, $bundleQty, $selectionQty,
477
  $multiplyQty);
483
  *
484
  * @param Mage_Catalog_Model_Product $bundleProduct
485
  * @param Mage_Catalog_Model_Product $selectionProduct
486
+ * @param float $bundleQty
487
+ * @param float $selectionQty
488
+ * @param bool $multiplyQty
489
+ * @param bool $takeTierPrice
490
+ * @return float
491
  */
492
  public function getSelectionFinalTotalPrice($bundleProduct, $selectionProduct, $bundleQty, $selectionQty,
493
+ $multiplyQty = true, $takeTierPrice = true)
494
  {
495
  if (is_null($selectionQty)) {
496
  $selectionQty = $selectionProduct->getSelectionQty();
513
  }
514
  }
515
 
516
+ $price = $this->getLowestPrice($bundleProduct, $price, $bundleQty);
 
 
 
 
517
 
518
  if ($multiplyQty) {
519
  $price *= $selectionQty;
522
  return $price;
523
  }
524
 
525
+ /**
526
+ * Returns the lowest price after applying any applicable bundle discounts
527
+ *
528
+ * @param Mage_Catalog_Model_Product $bundleProduct
529
+ * @param float|string $price
530
+ * @param int $bundleQty
531
+ * @return float
532
+ */
533
+ public function getLowestPrice($bundleProduct, $price, $bundleQty = 1)
534
+ {
535
+ $price *= 1;
536
+ return min($this->_getApp()->getStore()->roundPrice($price),
537
+ $this->_applyGroupPrice($bundleProduct, $price),
538
+ $this->_applyTierPrice($bundleProduct, $bundleQty, $price),
539
+ $this->_applySpecialPrice($bundleProduct, $price)
540
+ );
541
+ }
542
+
543
  /**
544
  * Apply group price for bundle product
545
  *
554
 
555
  if (is_numeric($groupPrice)) {
556
  $groupPrice = $finalPrice - ($finalPrice * ($groupPrice / 100));
557
+ $groupPrice = $this->_getApp()->getStore()->roundPrice($groupPrice);
558
  $result = min($finalPrice, $groupPrice);
559
  }
560
 
601
  * Apply tier price for bundle
602
  *
603
  * @param Mage_Catalog_Model_Product $product
604
+ * @param decimal $qty
605
+ * @param decimal $finalPrice
606
  * @return decimal
607
  */
608
  protected function _applyTierPrice($product, $qty, $finalPrice)
611
  return $finalPrice;
612
  }
613
 
614
+ $tierPrice = $product->getTierPrice($qty);
615
 
616
  if (is_numeric($tierPrice)) {
617
  $tierPrice = $finalPrice - ($finalPrice * ($tierPrice / 100));
618
+ $tierPrice = $this->_getApp()->getStore()->roundPrice($tierPrice);
619
  $finalPrice = min($finalPrice, $tierPrice);
620
  }
621
 
625
  /**
626
  * Get product tier price by qty
627
  *
628
+ * @param decimal $qty
629
  * @param Mage_Catalog_Model_Product $product
630
  * @return decimal
631
  */
644
 
645
  if (is_null($prices) || !is_array($prices)) {
646
  if (!is_null($qty)) {
647
+ return 0;
648
  }
649
  return array(array(
650
+ 'price' => 0,
651
+ 'website_price' => 0,
652
+ 'price_qty' => 1,
653
+ 'cust_group' => $allGroups
654
  ));
655
  }
656
 
679
  }
680
 
681
  if ($price['website_price'] > $prevPrice) {
682
+ $prevPrice = $price['website_price'];
683
+ $prevQty = $price['price_qty'];
684
+ $prevGroup = $price['cust_group'];
685
  }
686
  }
687
 
711
  /**
712
  * Calculate product price based on special price data and price rules
713
  *
714
+ * @param float $basePrice
715
+ * @param float $specialPrice
716
+ * @param string $specialPriceFrom
717
+ * @param string $specialPriceTo
718
  * @param float|null|false $rulePrice
719
+ * @param mixed $wId
720
+ * @param mixed $gId
721
+ * @param null|int $productId
722
  * @return float
723
  */
724
  public static function calculatePrice($basePrice, $specialPrice, $specialPriceFrom, $specialPriceTo,
725
+ $rulePrice = false, $wId = null, $gId = null, $productId = null)
726
  {
727
  $resource = Mage::getResourceSingleton('bundle/bundle');
728
  $selectionResource = Mage::getResourceSingleton('bundle/selection');
772
  $result['final_price'] = $selectionResource->getPriceFromIndex($result['product_id'], $qty, $store,
773
  $gId);
774
 
775
+ $selectionPrice = $result['final_price'] * $qty;
776
 
777
  if (isset($options[$result['option_id']])) {
778
  $options[$result['option_id']] = min($options[$result['option_id']], $selectionPrice);
787
  continue;
788
  }
789
  if ($result['selection_price_type']) {
790
+ $selectionPrice = $basePrice * $result['selection_price_value'] / 100;
791
  } else {
792
  $selectionPrice = $result['selection_price_value'];
793
  }
800
  $qty = $result['selection_qty'];
801
  }
802
 
803
+ $selectionPrice = $selectionPrice * $qty;
804
 
805
  if (isset($options[$result['option_id']])) {
806
  $options[$result['option_id']] = min($options[$result['option_id']], $selectionPrice);
856
  /**
857
  * Calculate and apply special price
858
  *
859
+ * @param float $finalPrice
860
+ * @param float $specialPrice
861
  * @param string $specialPriceFrom
862
  * @param string $specialPriceTo
863
+ * @param mixed $store
864
  * @return float
865
  */
866
  public static function calculateSpecialPrice($finalPrice, $specialPrice, $specialPriceFrom, $specialPriceTo,
867
+ $store = null)
868
  {
869
  if (!is_null($specialPrice) && $specialPrice != false) {
870
  if (Mage::app()->getLocale()->isStoreDateInInterval($store, $specialPriceFrom, $specialPriceTo)) {
871
+ $specialPrice = Mage::app()->getStore()->roundPrice($finalPrice * $specialPrice / 100);
872
+ $finalPrice = min($finalPrice, $specialPrice);
873
  }
874
  }
875
 
897
  return Mage::helper($name);
898
  }
899
 
900
+ /**
901
+ * Get Magento App instance
902
+ *
903
+ * @return Mage_Core_Model_App
904
+ */
905
+ protected function _getApp()
906
+ {
907
+ return Mage::app();
908
+ }
909
+
910
  /**
911
  * Check if product has required options
912
  *
app/code/core/Mage/Catalog/Block/Product/Abstract.php CHANGED
@@ -60,7 +60,7 @@ abstract class Mage_Catalog_Block_Product_Abstract extends Mage_Core_Block_Templ
60
  *
61
  * @var string
62
  */
63
- protected $_tierPriceDefaultTemplate = 'catalog/product/view/tierprices.phtml';
64
 
65
  /**
66
  * Price types
@@ -198,7 +198,7 @@ abstract class Mage_Catalog_Block_Product_Abstract extends Mage_Core_Block_Templ
198
  $stockItem = $product->getStockItem();
199
  if ($stockItem) {
200
  return ($stockItem->getMinSaleQty()
201
- && $stockItem->getMinSaleQty() > 0 ? $stockItem->getMinSaleQty() * 1 : null);
202
  }
203
  return null;
204
  }
@@ -377,13 +377,15 @@ abstract class Mage_Catalog_Block_Product_Abstract extends Mage_Core_Block_Templ
377
 
378
  return $this->getData('tier_price_template');
379
  }
 
380
  /**
381
  * Returns product tier price block html
382
  *
383
- * @param Mage_Catalog_Model_Product $product
 
384
  * @return string
385
  */
386
- public function getTierPriceHtml($product = null)
387
  {
388
  if (is_null($product)) {
389
  $product = $this->getProduct();
@@ -391,8 +393,22 @@ abstract class Mage_Catalog_Block_Product_Abstract extends Mage_Core_Block_Templ
391
  return $this->_getPriceBlock($product->getTypeId())
392
  ->setTemplate($this->getTierPriceTemplate())
393
  ->setProduct($product)
394
- ->setInGrouped($this->getProduct()->isGrouped())
395
- ->toHtml();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
396
  }
397
 
398
  /**
@@ -406,7 +422,7 @@ abstract class Mage_Catalog_Block_Product_Abstract extends Mage_Core_Block_Templ
406
  if (is_null($product)) {
407
  $product = $this->getProduct();
408
  }
409
- $prices = $product->getFormatedTierPrice();
410
 
411
  $res = array();
412
  if (is_array($prices)) {
60
  *
61
  * @var string
62
  */
63
+ protected $_tierPriceDefaultTemplate = 'catalog/product/view/tierprices.phtml';
64
 
65
  /**
66
  * Price types
198
  $stockItem = $product->getStockItem();
199
  if ($stockItem) {
200
  return ($stockItem->getMinSaleQty()
201
+ && $stockItem->getMinSaleQty() > 0 ? $stockItem->getMinSaleQty() * 1 : null);
202
  }
203
  return null;
204
  }
377
 
378
  return $this->getData('tier_price_template');
379
  }
380
+
381
  /**
382
  * Returns product tier price block html
383
  *
384
+ * @param null|Mage_Catalog_Model_Product $product
385
+ * @param null|Mage_Catalog_Model_Product $parent
386
  * @return string
387
  */
388
+ public function getTierPriceHtml($product = null, $parent = null)
389
  {
390
  if (is_null($product)) {
391
  $product = $this->getProduct();
393
  return $this->_getPriceBlock($product->getTypeId())
394
  ->setTemplate($this->getTierPriceTemplate())
395
  ->setProduct($product)
396
+ ->setInGrouped($product->isGrouped())
397
+ ->setParent($parent)
398
+ ->callParentToHtml();
399
+ }
400
+
401
+ /*
402
+ * Calls the object's to Html method.
403
+ * This method exists to make the code more testable.
404
+ * By having a protected wrapper for the final method toHtml, we can 'mock' out this method
405
+ * when unit testing
406
+ *
407
+ * @return string
408
+ */
409
+ protected function callParentToHtml()
410
+ {
411
+ return $this->toHtml();
412
  }
413
 
414
  /**
422
  if (is_null($product)) {
423
  $product = $this->getProduct();
424
  }
425
+ $prices = $product->getFormatedTierPrice();
426
 
427
  $res = array();
428
  if (is_array($prices)) {
app/code/core/Mage/Catalog/Block/Product/Price.php CHANGED
@@ -33,7 +33,18 @@
33
  */
34
  class Mage_Catalog_Block_Product_Price extends Mage_Catalog_Block_Product_Abstract
35
  {
 
 
 
 
 
36
  protected $_priceDisplayType = null;
 
 
 
 
 
 
37
  protected $_idSuffix = '';
38
 
39
  /**
@@ -50,17 +61,33 @@ class Mage_Catalog_Block_Product_Price extends Mage_Catalog_Block_Product_Abstra
50
  return $product;
51
  }
52
 
 
 
 
 
 
53
  public function getDisplayMinimalPrice()
54
  {
55
  return $this->_getData('display_minimal_price');
56
  }
57
 
 
 
 
 
 
 
58
  public function setIdSuffix($idSuffix)
59
  {
60
  $this->_idSuffix = $idSuffix;
61
  return $this;
62
  }
63
 
 
 
 
 
 
64
  public function getIdSuffix()
65
  {
66
  return $this->_idSuffix;
@@ -70,15 +97,22 @@ class Mage_Catalog_Block_Product_Price extends Mage_Catalog_Block_Product_Abstra
70
  * Get tier prices (formatted)
71
  *
72
  * @param Mage_Catalog_Model_Product $product
 
73
  * @return array
74
  */
75
- public function getTierPrices($product = null)
76
  {
77
  if (is_null($product)) {
78
  $product = $this->getProduct();
79
  }
80
  $prices = $product->getFormatedTierPrice();
81
 
 
 
 
 
 
 
82
  $res = array();
83
  if (is_array($prices)) {
84
  foreach ($prices as $price) {
@@ -96,8 +130,15 @@ class Mage_Catalog_Block_Product_Price extends Mage_Catalog_Block_Product_Abstra
96
  }
97
 
98
  if ($price['price'] < $productPrice) {
 
99
  $price['savePercent'] = ceil(100 - ((100 / $productPrice) * $price['price']));
100
 
 
 
 
 
 
 
101
  $tierPrice = Mage::app()->getStore()->convertPrice(
102
  Mage::helper('tax')->getPrice($product, $price['website_price'])
103
  );
33
  */
34
  class Mage_Catalog_Block_Product_Price extends Mage_Catalog_Block_Product_Abstract
35
  {
36
+ /**
37
+ * Price display type
38
+ *
39
+ * @var int
40
+ */
41
  protected $_priceDisplayType = null;
42
+
43
+ /**
44
+ * The id suffix
45
+ *
46
+ * @var string
47
+ */
48
  protected $_idSuffix = '';
49
 
50
  /**
61
  return $product;
62
  }
63
 
64
+ /**
65
+ * Returns the product's minimal price
66
+ *
67
+ * @return float
68
+ */
69
  public function getDisplayMinimalPrice()
70
  {
71
  return $this->_getData('display_minimal_price');
72
  }
73
 
74
+ /**
75
+ * Sets the id suffix
76
+ *
77
+ * @param string $idSuffix
78
+ * @return Mage_Catalog_Block_Product_Price
79
+ */
80
  public function setIdSuffix($idSuffix)
81
  {
82
  $this->_idSuffix = $idSuffix;
83
  return $this;
84
  }
85
 
86
+ /**
87
+ * Returns the id suffix
88
+ *
89
+ * @return string
90
+ */
91
  public function getIdSuffix()
92
  {
93
  return $this->_idSuffix;
97
  * Get tier prices (formatted)
98
  *
99
  * @param Mage_Catalog_Model_Product $product
100
+ * @param Mage_Catalog_Model_Product $parent
101
  * @return array
102
  */
103
+ public function getTierPrices($product = null, $parent = null)
104
  {
105
  if (is_null($product)) {
106
  $product = $this->getProduct();
107
  }
108
  $prices = $product->getFormatedTierPrice();
109
 
110
+ // if our parent is a bundle, then we need to further adjust our tier prices
111
+ if (isset($parent) && $parent->getTypeId() == Mage_Catalog_Model_Product_Type::TYPE_BUNDLE) {
112
+ /* @var $bundlePriceModel Mage_Bundle_Model_Product_Price */
113
+ $bundlePriceModel = Mage::getModel('bundle/product_price');
114
+ }
115
+
116
  $res = array();
117
  if (is_array($prices)) {
118
  foreach ($prices as $price) {
130
  }
131
 
132
  if ($price['price'] < $productPrice) {
133
+ // use the original prices to determine the percent savings
134
  $price['savePercent'] = ceil(100 - ((100 / $productPrice) * $price['price']));
135
 
136
+ // if applicable, adjust the tier prices
137
+ if (isset($bundlePriceModel)) {
138
+ $price['price'] = $bundlePriceModel->getLowestPrice($parent, $price['price']);
139
+ $price['website_price'] = $bundlePriceModel->getLowestPrice($parent, $price['website_price']);
140
+ }
141
+
142
  $tierPrice = Mage::app()->getStore()->convertPrice(
143
  Mage::helper('tax')->getPrice($product, $price['website_price'])
144
  );
app/code/core/Mage/Catalog/Block/Product/View.php CHANGED
@@ -153,8 +153,15 @@ class Mage_Catalog_Block_Product_View extends Mage_Catalog_Block_Product_Abstrac
153
 
154
  $_regularPrice = $product->getPrice();
155
  $_finalPrice = $product->getFinalPrice();
156
- $_priceInclTax = Mage::helper('tax')->getPrice($product, $_finalPrice, true);
157
- $_priceExclTax = Mage::helper('tax')->getPrice($product, $_finalPrice);
 
 
 
 
 
 
 
158
  $_tierPrices = array();
159
  $_tierPricesInclTax = array();
160
  foreach ($product->getTierPrice() as $tierPrice) {
153
 
154
  $_regularPrice = $product->getPrice();
155
  $_finalPrice = $product->getFinalPrice();
156
+ if ($product->getTypeId() == Mage_Catalog_Model_Product_Type::TYPE_BUNDLE) {
157
+ $_priceInclTax = Mage::helper('tax')->getPrice($product, $_finalPrice, true,
158
+ null, null, null, null, null, false);
159
+ $_priceExclTax = Mage::helper('tax')->getPrice($product, $_finalPrice, false,
160
+ null, null, null, null, null, false);
161
+ } else {
162
+ $_priceInclTax = Mage::helper('tax')->getPrice($product, $_finalPrice, true);
163
+ $_priceExclTax = Mage::helper('tax')->getPrice($product, $_finalPrice);
164
+ }
165
  $_tierPrices = array();
166
  $_tierPricesInclTax = array();
167
  foreach ($product->getTierPrice() as $tierPrice) {
app/code/core/Mage/Catalog/Helper/Product/Compare.php CHANGED
@@ -102,7 +102,8 @@ class Mage_Catalog_Helper_Product_Compare extends Mage_Core_Helper_Url
102
  {
103
  return array(
104
  'product' => $product->getId(),
105
- Mage_Core_Controller_Front_Action::PARAM_NAME_URL_ENCODED => $this->getEncodedUrl()
 
106
  );
107
  }
108
 
102
  {
103
  return array(
104
  'product' => $product->getId(),
105
+ Mage_Core_Controller_Front_Action::PARAM_NAME_URL_ENCODED => $this->getEncodedUrl(),
106
+ Mage_Core_Model_Url::FORM_KEY => $this->_getSingletonModel('core/session')->getFormKey()
107
  );
108
  }
109
 
app/code/core/Mage/Catalog/Model/Resource/Product/Indexer/Eav/Source.php CHANGED
@@ -211,7 +211,8 @@ class Mage_Catalog_Model_Resource_Product_Indexer_Eav_Source
211
  'pvs.entity_id = pvd.entity_id AND pvs.attribute_id = pvd.attribute_id'
212
  . ' AND pvs.store_id=cs.store_id',
213
  array('value' => $productValueExpression))
214
- ->where('pvd.store_id=?', Mage_Catalog_Model_Abstract::DEFAULT_STORE_ID)
 
215
  ->where('cs.store_id!=?', Mage_Catalog_Model_Abstract::DEFAULT_STORE_ID)
216
  ->where('pvd.attribute_id IN(?)', $attrIds);
217
 
211
  'pvs.entity_id = pvd.entity_id AND pvs.attribute_id = pvd.attribute_id'
212
  . ' AND pvs.store_id=cs.store_id',
213
  array('value' => $productValueExpression))
214
+ ->where('pvd.store_id=?',
215
+ $adapter->getIfNullSql('pvs.store_id', Mage_Catalog_Model_Abstract::DEFAULT_STORE_ID))
216
  ->where('cs.store_id!=?', Mage_Catalog_Model_Abstract::DEFAULT_STORE_ID)
217
  ->where('pvd.attribute_id IN(?)', $attrIds);
218
 
app/code/core/Mage/Catalog/Model/Resource/Product/Option/Value.php CHANGED
@@ -227,7 +227,7 @@ class Mage_Catalog_Model_Resource_Product_Option_Value extends Mage_Core_Model_R
227
  }
228
  } else if ($object->getData('scope', 'title')) {
229
  $where = array(
230
- 'option_type_id = ?' => (int)$optionTypeId,
231
  'store_id = ?' => (int)$object->getStoreId()
232
  );
233
  $this->_getWriteAdapter()->delete($titleTable, $where);
@@ -317,7 +317,7 @@ class Mage_Catalog_Model_Resource_Product_Option_Value extends Mage_Core_Model_R
317
  foreach ($valueCond as $oldTypeId => $newTypeId) {
318
  // price
319
  $priceTable = $this->getTable('catalog/product_option_type_price');
320
- $columns= array(
321
  new Zend_Db_Expr($newTypeId),
322
  'store_id', 'price', 'price_type'
323
  );
@@ -332,7 +332,7 @@ class Mage_Catalog_Model_Resource_Product_Option_Value extends Mage_Core_Model_R
332
 
333
  // title
334
  $titleTable = $this->getTable('catalog/product_option_type_title');
335
- $columns= array(
336
  new Zend_Db_Expr($newTypeId),
337
  'store_id', 'title'
338
  );
227
  }
228
  } else if ($object->getData('scope', 'title')) {
229
  $where = array(
230
+ 'option_type_id = ?' => (int)$object->getId(),
231
  'store_id = ?' => (int)$object->getStoreId()
232
  );
233
  $this->_getWriteAdapter()->delete($titleTable, $where);
317
  foreach ($valueCond as $oldTypeId => $newTypeId) {
318
  // price
319
  $priceTable = $this->getTable('catalog/product_option_type_price');
320
+ $columns = array(
321
  new Zend_Db_Expr($newTypeId),
322
  'store_id', 'price', 'price_type'
323
  );
332
 
333
  // title
334
  $titleTable = $this->getTable('catalog/product_option_type_title');
335
+ $columns = array(
336
  new Zend_Db_Expr($newTypeId),
337
  'store_id', 'title'
338
  );
app/code/core/Mage/Catalog/Model/Resource/Product/Status.php CHANGED
@@ -70,7 +70,8 @@ class Mage_Catalog_Model_Resource_Product_Status extends Mage_Core_Model_Resourc
70
  protected function _getProductAttribute($attribute)
71
  {
72
  if (empty($this->_productAttributes[$attribute])) {
73
- $this->_productAttributes[$attribute] = Mage::getSingleton('catalog/product')->getResource()->getAttribute($attribute);
 
74
  }
75
  return $this->_productAttributes[$attribute];
76
  }
@@ -129,12 +130,6 @@ class Mage_Catalog_Model_Resource_Product_Status extends Mage_Core_Model_Resourc
129
  ->where('store_id = :store_id')
130
  ->where('entity_id = :product_id');
131
 
132
- $binds = array(
133
- 'attribute_id' => $statusAttributeId,
134
- 'store_id' => $storeId,
135
- 'product_id' => $productId
136
- );
137
-
138
  $row = $adapter->fetchRow($select);
139
 
140
  if ($row) {
@@ -189,11 +184,12 @@ class Mage_Catalog_Model_Resource_Product_Status extends Mage_Core_Model_Resourc
189
  $select = $adapter->select()
190
  ->from(
191
  array('t1' => $attributeTable),
192
- array('value' => $valueCheckSql))
193
  ->joinLeft(
194
  array('t2' => $attributeTable),
195
- 't1.entity_id = t2.entity_id AND t1.attribute_id = t2.attribute_id AND t2.store_id = ' . (int)$storeId,
196
- array('t1.entity_id')
 
197
  )
198
  ->where('t1.store_id = ?', Mage_Core_Model_App::ADMIN_STORE_ID)
199
  ->where('t1.attribute_id = ?', $attribute->getAttributeId())
70
  protected function _getProductAttribute($attribute)
71
  {
72
  if (empty($this->_productAttributes[$attribute])) {
73
+ $this->_productAttributes[$attribute] =
74
+ Mage::getSingleton('catalog/product')->getResource()->getAttribute($attribute);
75
  }
76
  return $this->_productAttributes[$attribute];
77
  }
130
  ->where('store_id = :store_id')
131
  ->where('entity_id = :product_id');
132
 
 
 
 
 
 
 
133
  $row = $adapter->fetchRow($select);
134
 
135
  if ($row) {
184
  $select = $adapter->select()
185
  ->from(
186
  array('t1' => $attributeTable),
187
+ array('entity_id' => 't1.entity_id', 'value' => $valueCheckSql))
188
  ->joinLeft(
189
  array('t2' => $attributeTable),
190
+ 't1.entity_id = t2.entity_id AND t1.attribute_id = t2.attribute_id AND t2.store_id = '
191
+ . (int)$storeId,
192
+ array('')
193
  )
194
  ->where('t1.store_id = ?', Mage_Core_Model_App::ADMIN_STORE_ID)
195
  ->where('t1.attribute_id = ?', $attribute->getAttributeId())
app/code/core/Mage/Catalog/Model/Resource/Product/Type/Configurable.php CHANGED
@@ -220,7 +220,7 @@ class Mage_Catalog_Model_Resource_Product_Type_Configurable extends Mage_Core_Mo
220
  array()
221
  )->where('super_attribute.product_id = ?', $product->getId());
222
 
223
- $attributesOptionsData[$superAttribute->getAttributeId()] = $this->_getReadAdapter()->fetchAssoc($select);
224
  }
225
  return $attributesOptionsData;
226
  }
220
  array()
221
  )->where('super_attribute.product_id = ?', $product->getId());
222
 
223
+ $attributesOptionsData[$superAttribute->getAttributeId()] = $this->_getReadAdapter()->fetchAll($select);
224
  }
225
  return $attributesOptionsData;
226
  }
app/code/core/Mage/Catalog/controllers/Product/CompareController.php CHANGED
@@ -74,6 +74,11 @@ class Mage_Catalog_Product_CompareController extends Mage_Core_Controller_Front_
74
  */
75
  public function addAction()
76
  {
 
 
 
 
 
77
  $productId = (int) $this->getRequest()->getParam('product');
78
  if ($productId
79
  && (Mage::getSingleton('log/visitor')->getId() || Mage::getSingleton('customer/session')->isLoggedIn())
74
  */
75
  public function addAction()
76
  {
77
+ if (!$this->_validateFormKey()) {
78
+ $this->_redirectReferer();
79
+ return;
80
+ }
81
+
82
  $productId = (int) $this->getRequest()->getParam('product');
83
  if ($productId
84
  && (Mage::getSingleton('log/visitor')->getId() || Mage::getSingleton('customer/session')->isLoggedIn())
app/code/core/Mage/Catalog/etc/wsi.xml CHANGED
@@ -347,8 +347,8 @@
347
  </xsd:complexType>
348
  <xsd:complexType name="catalogProductAttributeFrontendLabelEntity">
349
  <xsd:sequence>
350
- <element name="store_id" type="xsd:string" />
351
- <element name="label" type="xsd:string" />
352
  </xsd:sequence>
353
  </xsd:complexType>
354
  <xsd:complexType name="catalogProductAttributeFrontendLabelArray">
347
  </xsd:complexType>
348
  <xsd:complexType name="catalogProductAttributeFrontendLabelEntity">
349
  <xsd:sequence>
350
+ <xsd:element name="store_id" type="xsd:string"/>
351
+ <xsd:element name="label" type="xsd:string"/>
352
  </xsd:sequence>
353
  </xsd:complexType>
354
  <xsd:complexType name="catalogProductAttributeFrontendLabelArray">
app/code/core/Mage/CatalogInventory/Model/Observer.php CHANGED
@@ -50,6 +50,11 @@ class Mage_CatalogInventory_Model_Observer
50
  */
51
  protected $_checkedQuoteItems = array();
52
 
 
 
 
 
 
53
  protected $_itemsForReindex = array();
54
 
55
  /**
@@ -174,9 +179,10 @@ class Mage_CatalogInventory_Model_Observer
174
  'use_config_min_sale_qty' => 1,
175
  'use_config_max_sale_qty' => 1,
176
  'use_config_backorders' => 1,
177
- 'use_config_notify_stock_qty'=> 1
178
  );
179
- if ($currentStockItem = $currentProduct->getStockItem()) {
 
180
  $stockData += array(
181
  'use_config_enable_qty_inc' => $currentStockItem->getData('use_config_enable_qty_inc'),
182
  'enable_qty_increments' => $currentStockItem->getData('enable_qty_increments'),
@@ -339,7 +345,8 @@ class Mage_CatalogInventory_Model_Observer
339
  /**
340
  * Check item for options
341
  */
342
- if (($options = $quoteItem->getQtyOptions()) && $qty > 0) {
 
343
  $qty = $quoteItem->getProduct()->getTypeInstance(true)->prepareQuoteItemQty($qty, $quoteItem->getProduct());
344
  $quoteItem->setData('qty', $qty);
345
 
@@ -367,6 +374,7 @@ class Mage_CatalogInventory_Model_Observer
367
  }
368
  }
369
 
 
370
  foreach ($options as $option) {
371
  $optionValue = $option->getValue();
372
  /* @var $option Mage_Sales_Model_Quote_Item_Option */
@@ -426,6 +434,7 @@ class Mage_CatalogInventory_Model_Observer
426
 
427
  if ($result->getHasError()) {
428
  $option->setHasError(true);
 
429
 
430
  $quoteItem->addErrorInfo(
431
  'cataloginventory',
@@ -439,7 +448,7 @@ class Mage_CatalogInventory_Model_Observer
439
  Mage_CatalogInventory_Helper_Data::ERROR_QTY,
440
  $result->getQuoteMessage()
441
  );
442
- } else {
443
  // Delete error from item and its quote, if it was set due to qty lack
444
  $this->_removeErrorsFromQuoteAndItem($quoteItem, Mage_CatalogInventory_Helper_Data::ERROR_QTY);
445
  }
@@ -727,7 +736,7 @@ class Mage_CatalogInventory_Model_Observer
727
  }
728
  }
729
 
730
- if( count($productIds)) {
731
  Mage::getResourceSingleton('cataloginventory/indexer_stock')->reindexProducts($productIds);
732
  }
733
 
@@ -773,8 +782,8 @@ class Mage_CatalogInventory_Model_Observer
773
  $items[$item->getProductId()]['qty'] += $qty;
774
  } else {
775
  $items[$item->getProductId()] = array(
776
- 'qty' => $qty,
777
- 'item'=> null,
778
  );
779
  }
780
  }
@@ -795,7 +804,8 @@ class Mage_CatalogInventory_Model_Observer
795
  $children = $item->getChildrenItems();
796
  $qty = $item->getQtyOrdered() - max($item->getQtyShipped(), $item->getQtyInvoiced()) - $item->getQtyCanceled();
797
 
798
- if ($item->getId() && ($productId = $item->getProductId()) && empty($children) && $qty) {
 
799
  Mage::getSingleton('cataloginventory/stock')->backItemQty($productId, $qty);
800
  }
801
 
50
  */
51
  protected $_checkedQuoteItems = array();
52
 
53
+ /**
54
+ * Array of items that need to be reindexed
55
+ *
56
+ * @var array
57
+ */
58
  protected $_itemsForReindex = array();
59
 
60
  /**
179
  'use_config_min_sale_qty' => 1,
180
  'use_config_max_sale_qty' => 1,
181
  'use_config_backorders' => 1,
182
+ 'use_config_notify_stock_qty' => 1
183
  );
184
+ $currentStockItem = $currentProduct->getStockItem();
185
+ if ($currentStockItem) {
186
  $stockData += array(
187
  'use_config_enable_qty_inc' => $currentStockItem->getData('use_config_enable_qty_inc'),
188
  'enable_qty_increments' => $currentStockItem->getData('enable_qty_increments'),
345
  /**
346
  * Check item for options
347
  */
348
+ $options = $quoteItem->getQtyOptions();
349
+ if ($options && $qty > 0) {
350
  $qty = $quoteItem->getProduct()->getTypeInstance(true)->prepareQuoteItemQty($qty, $quoteItem->getProduct());
351
  $quoteItem->setData('qty', $qty);
352
 
374
  }
375
  }
376
 
377
+ $quoteItemHasErrors = false;
378
  foreach ($options as $option) {
379
  $optionValue = $option->getValue();
380
  /* @var $option Mage_Sales_Model_Quote_Item_Option */
434
 
435
  if ($result->getHasError()) {
436
  $option->setHasError(true);
437
+ $quoteItemHasErrors = true;
438
 
439
  $quoteItem->addErrorInfo(
440
  'cataloginventory',
448
  Mage_CatalogInventory_Helper_Data::ERROR_QTY,
449
  $result->getQuoteMessage()
450
  );
451
+ } elseif (!$quoteItemHasErrors) {
452
  // Delete error from item and its quote, if it was set due to qty lack
453
  $this->_removeErrorsFromQuoteAndItem($quoteItem, Mage_CatalogInventory_Helper_Data::ERROR_QTY);
454
  }
736
  }
737
  }
738
 
739
+ if (count($productIds)) {
740
  Mage::getResourceSingleton('cataloginventory/indexer_stock')->reindexProducts($productIds);
741
  }
742
 
782
  $items[$item->getProductId()]['qty'] += $qty;
783
  } else {
784
  $items[$item->getProductId()] = array(
785
+ 'qty' => $qty,
786
+ 'item' => null,
787
  );
788
  }
789
  }
804
  $children = $item->getChildrenItems();
805
  $qty = $item->getQtyOrdered() - max($item->getQtyShipped(), $item->getQtyInvoiced()) - $item->getQtyCanceled();
806
 
807
+ $productId = $item->getProductId();
808
+ if ($item->getId() && $productId && empty($children) && $qty) {
809
  Mage::getSingleton('cataloginventory/stock')->backItemQty($productId, $qty);
810
  }
811
 
app/code/core/Mage/CatalogRule/Model/Resource/Rule.php CHANGED
@@ -246,7 +246,7 @@ class Mage_CatalogRule_Model_Resource_Rule extends Mage_Rule_Model_Resource_Abst
246
  ));
247
 
248
  if (count($productIds) > 0) {
249
- $selectByStore->where('p.entity_id IN (?)', $productIds);
250
  }
251
 
252
  $selects = $write->selectsByRange('entity_id', $selectByStore, self::RANGE_PRODUCT_STEP);
246
  ));
247
 
248
  if (count($productIds) > 0) {
249
+ $selectByStore->where('p.entity_id IN (?)', array_keys($productIds));
250
  }
251
 
252
  $selects = $write->selectsByRange('entity_id', $selectByStore, self::RANGE_PRODUCT_STEP);
app/code/core/Mage/CatalogRule/Model/Rule/Condition/Product.php CHANGED
@@ -89,11 +89,13 @@ class Mage_CatalogRule_Model_Rule_Condition_Product extends Mage_Rule_Model_Cond
89
  */
90
  protected function _getAttributeValue($object)
91
  {
 
92
  $storeId = $object->getStoreId();
93
  $defaultStoreId = Mage_Core_Model_App::ADMIN_STORE_ID;
94
  $productValues = isset($this->_entityAttributeValues[$object->getId()])
95
  ? $this->_entityAttributeValues[$object->getId()] : array();
96
- $defaultValue = isset($productValues[$defaultStoreId]) ? $productValues[$defaultStoreId] : null;
 
97
  $value = isset($productValues[$storeId]) ? $productValues[$storeId] : $defaultValue;
98
 
99
  $value = $this->_prepareDatetimeValue($value, $object);
89
  */
90
  protected function _getAttributeValue($object)
91
  {
92
+ $attrCode = $this->getAttribute();
93
  $storeId = $object->getStoreId();
94
  $defaultStoreId = Mage_Core_Model_App::ADMIN_STORE_ID;
95
  $productValues = isset($this->_entityAttributeValues[$object->getId()])
96
  ? $this->_entityAttributeValues[$object->getId()] : array();
97
+ $defaultValue = isset($productValues[$defaultStoreId])
98
+ ? $productValues[$defaultStoreId] : $object->getData($attrCode);
99
  $value = isset($productValues[$storeId]) ? $productValues[$storeId] : $defaultValue;
100
 
101
  $value = $this->_prepareDatetimeValue($value, $object);
app/code/core/Mage/CatalogSearch/Helper/Data.php CHANGED
@@ -31,7 +31,14 @@
31
  */
32
  class Mage_CatalogSearch_Helper_Data extends Mage_Core_Helper_Abstract
33
  {
 
 
 
34
  const QUERY_VAR_NAME = 'q';
 
 
 
 
35
  const MAX_QUERY_LEN = 200;
36
 
37
  /**
@@ -166,7 +173,7 @@ class Mage_CatalogSearch_Helper_Data extends Mage_Core_Helper_Abstract
166
  {
167
  return $this->_getUrl('catalogsearch/result', array(
168
  '_query' => array(self::QUERY_VAR_NAME => $query),
169
- '_secure' => Mage::app()->getFrontController()->getRequest()->isSecure()
170
  ));
171
  }
172
 
@@ -178,10 +185,20 @@ class Mage_CatalogSearch_Helper_Data extends Mage_Core_Helper_Abstract
178
  public function getSuggestUrl()
179
  {
180
  return $this->_getUrl('catalogsearch/ajax/suggest', array(
181
- '_secure' => Mage::app()->getFrontController()->getRequest()->isSecure()
182
  ));
183
  }
184
 
 
 
 
 
 
 
 
 
 
 
185
  /**
186
  * Retrieve search term url
187
  *
31
  */
32
  class Mage_CatalogSearch_Helper_Data extends Mage_Core_Helper_Abstract
33
  {
34
+ /**
35
+ * Query variable name
36
+ */
37
  const QUERY_VAR_NAME = 'q';
38
+
39
+ /*
40
+ * Maximum query length
41
+ */
42
  const MAX_QUERY_LEN = 200;
43
 
44
  /**
173
  {
174
  return $this->_getUrl('catalogsearch/result', array(
175
  '_query' => array(self::QUERY_VAR_NAME => $query),
176
+ '_secure' => $this->_getApp()->getFrontController()->getRequest()->isSecure()
177
  ));
178
  }
179
 
185
  public function getSuggestUrl()
186
  {
187
  return $this->_getUrl('catalogsearch/ajax/suggest', array(
188
+ '_secure' => $this->_getApp()->getStore()->isCurrentlySecure()
189
  ));
190
  }
191
 
192
+ /**
193
+ * Get App
194
+ *
195
+ * @return Mage_Core_Model_App
196
+ */
197
+ protected function _getApp()
198
+ {
199
+ return Mage::app();
200
+ }
201
+
202
  /**
203
  * Retrieve search term url
204
  *
app/code/core/Mage/Checkout/Block/Cart/Item/Renderer.php CHANGED
@@ -442,6 +442,9 @@ class Mage_Checkout_Block_Cart_Item_Renderer extends Mage_Core_Block_Template
442
  */
443
  public function getCacheTags()
444
  {
445
- return array_merge(parent::getCacheTags(), $this->getProduct()->getCacheIdTags());
 
 
 
446
  }
447
  }
442
  */
443
  public function getCacheTags()
444
  {
445
+ $tags = $this->getProduct()->getCacheIdTags();
446
+ $tags = is_array($tags) ? $tags : array();
447
+
448
+ return array_merge(parent::getCacheTags(), $tags);
449
  }
450
  }
app/code/core/Mage/Checkout/Helper/Data.php CHANGED
@@ -93,6 +93,7 @@ class Mage_Checkout_Helper_Data extends Mage_Core_Helper_Abstract
93
 
94
  /**
95
  * Get sales item (quote item, order item etc) price including tax based on row total and tax amount
 
96
  *
97
  * @param Varien_Object $item
98
  * @return float
@@ -103,9 +104,9 @@ class Mage_Checkout_Helper_Data extends Mage_Core_Helper_Abstract
103
  return $item->getPriceInclTax();
104
  }
105
  $qty = ($item->getQty() ? $item->getQty() : ($item->getQtyOrdered() ? $item->getQtyOrdered() : 1));
106
- $taxAmount = $item->getTaxAmount() + $item->getDiscountTaxCompensation();
107
- $price = (floatval($qty)) ? ($item->getRowTotal() + $taxAmount)/$qty : 0;
108
- return Mage::app()->getStore()->roundPrice($price);
109
  }
110
 
111
  /**
@@ -119,21 +120,46 @@ class Mage_Checkout_Helper_Data extends Mage_Core_Helper_Abstract
119
  if ($item->getRowTotalInclTax()) {
120
  return $item->getRowTotalInclTax();
121
  }
122
- $tax = $item->getTaxAmount() + $item->getDiscountTaxCompensation();
 
 
 
123
  return $item->getRowTotal() + $tax;
124
  }
125
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
126
  public function getBasePriceInclTax($item)
127
  {
128
  $qty = ($item->getQty() ? $item->getQty() : ($item->getQtyOrdered() ? $item->getQtyOrdered() : 1));
129
- $taxAmount = $item->getBaseTaxAmount() + $item->getBaseDiscountTaxCompensation();
130
- $price = (floatval($qty)) ? ($item->getBaseRowTotal() + $taxAmount)/$qty : 0;
131
- return Mage::app()->getStore()->roundPrice($price);
132
  }
133
 
 
 
 
 
 
 
134
  public function getBaseSubtotalInclTax($item)
135
  {
136
- $tax = $item->getBaseTaxAmount() + $item->getBaseDiscountTaxCompensation();
 
137
  return $item->getBaseRowTotal()+$tax;
138
  }
139
 
@@ -193,32 +219,32 @@ class Mage_Checkout_Helper_Data extends Mage_Core_Helper_Abstract
193
  foreach ($checkout->getAllVisibleItems() as $_item) {
194
  /* @var $_item Mage_Sales_Model_Quote_Item */
195
  $items .= $_item->getProduct()->getName() . ' x '. $_item->getQty() . ' '
196
- . $checkout->getStoreCurrencyCode() . ' '
197
- . $_item->getProduct()->getFinalPrice($_item->getQty()) . "\n";
198
  }
199
  $total = $checkout->getStoreCurrencyCode() . ' ' . $checkout->getGrandTotal();
200
 
201
  foreach ($sendTo as $recipient) {
202
  $mailTemplate->setDesignConfig(array('area'=>'frontend', 'store'=>$checkout->getStoreId()))
203
  ->sendTransactional(
204
- $template,
205
- Mage::getStoreConfig('checkout/payment_failed/identity', $checkout->getStoreId()),
206
- $recipient['email'],
207
- $recipient['name'],
208
- array(
209
- 'reason' => $message,
210
- 'checkoutType' => $checkoutType,
211
- 'dateAndTime' => Mage::app()->getLocale()->date(),
212
- 'customer' => $checkout->getCustomerFirstname() . ' ' . $checkout->getCustomerLastname(),
213
- 'customerEmail' => $checkout->getCustomerEmail(),
214
- 'billingAddress' => $checkout->getBillingAddress(),
215
- 'shippingAddress' => $checkout->getShippingAddress(),
216
- 'shippingMethod' => Mage::getStoreConfig('carriers/'.$shippingMethod.'/title'),
217
- 'paymentMethod' => Mage::getStoreConfig('payment/'.$paymentMethod.'/title'),
218
- 'items' => nl2br($items),
219
- 'total' => $total
220
- )
221
- );
222
  }
223
 
224
  $translate->setTranslateInline(true);
@@ -255,7 +281,7 @@ class Mage_Checkout_Helper_Data extends Mage_Core_Helper_Abstract
255
  && (($quote->getItemsSummaryQty() - $quote->getItemVirtualQty()) > 0)
256
  && ($quote->getItemsSummaryQty() <= $maximunQty)
257
  && !$quote->hasNominalItems()
258
- ;
259
  }
260
 
261
  /**
93
 
94
  /**
95
  * Get sales item (quote item, order item etc) price including tax based on row total and tax amount
96
+ * excluding weee tax
97
  *
98
  * @param Varien_Object $item
99
  * @return float
104
  return $item->getPriceInclTax();
105
  }
106
  $qty = ($item->getQty() ? $item->getQty() : ($item->getQtyOrdered() ? $item->getQtyOrdered() : 1));
107
+
108
+ //Unit price is rowtotal/qty
109
+ return $qty > 0 ? $this->getSubtotalInclTax($item)/$qty :0;
110
  }
111
 
112
  /**
120
  if ($item->getRowTotalInclTax()) {
121
  return $item->getRowTotalInclTax();
122
  }
123
+ //Since tax amount contains weee tax
124
+ $tax = $item->getTaxAmount() + $item->getDiscountTaxCompensation()
125
+ - $this->_getWeeeHelper()->getTotalRowTaxAppliedForWeeeTax($item);;
126
+
127
  return $item->getRowTotal() + $tax;
128
  }
129
 
130
+ /**
131
+ * Returns the helper for weee
132
+ *
133
+ * @return Mage_Weee_Helper_Data
134
+ */
135
+ protected function _getWeeeHelper()
136
+ {
137
+ return Mage::helper('weee');
138
+ }
139
+
140
+ /**
141
+ * Get the base price of the item including tax , excluding weee
142
+ *
143
+ * @param Varien_Object $item
144
+ * @return float
145
+ */
146
  public function getBasePriceInclTax($item)
147
  {
148
  $qty = ($item->getQty() ? $item->getQty() : ($item->getQtyOrdered() ? $item->getQtyOrdered() : 1));
149
+
150
+ return $qty > 0 ? $this->getBaseSubtotalInclTax($item) / $qty : 0;
 
151
  }
152
 
153
+ /**
154
+ * Get sales item (quote item, order item etc) row total price including tax excluding wee
155
+ *
156
+ * @param Varien_Object $item
157
+ * @return float
158
+ */
159
  public function getBaseSubtotalInclTax($item)
160
  {
161
+ $tax = $item->getBaseTaxAmount() + $item->getBaseDiscountTaxCompensation()
162
+ - $this->_getWeeeHelper()->getBaseTotalRowTaxAppliedForWeeeTax($item);
163
  return $item->getBaseRowTotal()+$tax;
164
  }
165
 
219
  foreach ($checkout->getAllVisibleItems() as $_item) {
220
  /* @var $_item Mage_Sales_Model_Quote_Item */
221
  $items .= $_item->getProduct()->getName() . ' x '. $_item->getQty() . ' '
222
+ . $checkout->getStoreCurrencyCode() . ' '
223
+ . $_item->getProduct()->getFinalPrice($_item->getQty()) . "\n";
224
  }
225
  $total = $checkout->getStoreCurrencyCode() . ' ' . $checkout->getGrandTotal();
226
 
227
  foreach ($sendTo as $recipient) {
228
  $mailTemplate->setDesignConfig(array('area'=>'frontend', 'store'=>$checkout->getStoreId()))
229
  ->sendTransactional(
230
+ $template,
231
+ Mage::getStoreConfig('checkout/payment_failed/identity', $checkout->getStoreId()),
232
+ $recipient['email'],
233
+ $recipient['name'],
234
+ array(
235
+ 'reason' => $message,
236
+ 'checkoutType' => $checkoutType,
237
+ 'dateAndTime' => Mage::app()->getLocale()->date(),
238
+ 'customer' => $checkout->getCustomerFirstname() . ' ' . $checkout->getCustomerLastname(),
239
+ 'customerEmail' => $checkout->getCustomerEmail(),
240
+ 'billingAddress' => $checkout->getBillingAddress(),
241
+ 'shippingAddress' => $checkout->getShippingAddress(),
242
+ 'shippingMethod' => Mage::getStoreConfig('carriers/'.$shippingMethod.'/title'),
243
+ 'paymentMethod' => Mage::getStoreConfig('payment/'.$paymentMethod.'/title'),
244
+ 'items' => nl2br($items),
245
+ 'total' => $total
246
+ )
247
+ );
248
  }
249
 
250
  $translate->setTranslateInline(true);
281
  && (($quote->getItemsSummaryQty() - $quote->getItemVirtualQty()) > 0)
282
  && ($quote->getItemsSummaryQty() <= $maximunQty)
283
  && !$quote->hasNominalItems()
284
+ ;
285
  }
286
 
287
  /**
app/code/core/Mage/Checkout/Model/Cart/Product/Api.php CHANGED
@@ -31,7 +31,6 @@
31
  * @package Mage_Checkout
32
  * @author Magento Core Team <core@magentocommerce.com>
33
  */
34
-
35
  class Mage_Checkout_Model_Cart_Product_Api extends Mage_Checkout_Model_Api_Resource_Product
36
  {
37
  /**
@@ -51,7 +50,7 @@ class Mage_Checkout_Model_Cart_Product_Api extends Mage_Checkout_Model_Api_Resou
51
  * @param $store
52
  * @return bool
53
  */
54
- public function add($quoteId, $productsData, $store=null)
55
  {
56
  $quote = $this->_getQuote($quoteId, $store);
57
  if (empty($store)) {
@@ -91,7 +90,7 @@ class Mage_Checkout_Model_Cart_Product_Api extends Mage_Checkout_Model_Api_Resou
91
 
92
  try {
93
  $quote->collectTotals()->save();
94
- } catch(Exception $e) {
95
  $this->_fault("add_product_quote_save_fault", $e->getMessage());
96
  }
97
 
@@ -104,7 +103,7 @@ class Mage_Checkout_Model_Cart_Product_Api extends Mage_Checkout_Model_Api_Resou
104
  * @param $store
105
  * @return bool
106
  */
107
- public function update($quoteId, $productsData, $store=null)
108
  {
109
  $quote = $this->_getQuote($quoteId, $store);
110
  if (empty($store)) {
@@ -145,8 +144,8 @@ class Mage_Checkout_Model_Cart_Product_Api extends Mage_Checkout_Model_Api_Resou
145
  }
146
 
147
  try {
148
- $quote->save();
149
- } catch(Exception $e) {
150
  $this->_fault("update_product_quote_save_fault", $e->getMessage());
151
  }
152
 
@@ -159,7 +158,7 @@ class Mage_Checkout_Model_Cart_Product_Api extends Mage_Checkout_Model_Api_Resou
159
  * @param $store
160
  * @return bool
161
  */
162
- public function remove($quoteId, $productsData, $store=null)
163
  {
164
  $quote = $this->_getQuote($quoteId, $store);
165
  if (empty($store)) {
@@ -201,8 +200,8 @@ class Mage_Checkout_Model_Cart_Product_Api extends Mage_Checkout_Model_Api_Resou
201
  }
202
 
203
  try {
204
- $quote->save();
205
- } catch(Exception $e) {
206
  $this->_fault("remove_product_quote_save_fault", $e->getMessage());
207
  }
208
 
@@ -249,7 +248,7 @@ class Mage_Checkout_Model_Cart_Product_Api extends Mage_Checkout_Model_Api_Resou
249
  * @param $store
250
  * @return bool
251
  */
252
- public function moveToCustomerQuote($quoteId, $productsData, $store=null)
253
  {
254
  $quote = $this->_getQuote($quoteId, $store);
255
 
@@ -281,7 +280,7 @@ class Mage_Checkout_Model_Cart_Product_Api extends Mage_Checkout_Model_Api_Resou
281
  }
282
 
283
  $errors = array();
284
- foreach($productsData as $key => $productItem){
285
  if (isset($productItem['product_id'])) {
286
  $productByItem = $this->_getProduct($productItem['product_id'], $store, "id");
287
  } else if (isset($productItem['sku'])) {
@@ -295,7 +294,7 @@ class Mage_Checkout_Model_Cart_Product_Api extends Mage_Checkout_Model_Api_Resou
295
  /** @var $quoteItem Mage_Sales_Model_Quote_Item */
296
  $quoteItem = $this->_getQuoteItemByProduct($quote, $productByItem,
297
  $this->_getProductRequest($productItem));
298
- if($quoteItem && $quoteItem->getId()){
299
  $newQuoteItem = clone $quoteItem;
300
  $newQuoteItem->setId(null);
301
  $customerQuote->addItem($newQuoteItem);
31
  * @package Mage_Checkout
32
  * @author Magento Core Team <core@magentocommerce.com>
33
  */
 
34
  class Mage_Checkout_Model_Cart_Product_Api extends Mage_Checkout_Model_Api_Resource_Product
35
  {
36
  /**
50
  * @param $store
51
  * @return bool
52
  */
53
+ public function add($quoteId, $productsData, $store = null)
54
  {
55
  $quote = $this->_getQuote($quoteId, $store);
56
  if (empty($store)) {
90
 
91
  try {
92
  $quote->collectTotals()->save();
93
+ } catch (Exception $e) {
94
  $this->_fault("add_product_quote_save_fault", $e->getMessage());
95
  }
96
 
103
  * @param $store
104
  * @return bool
105
  */
106
+ public function update($quoteId, $productsData, $store = null)
107
  {
108
  $quote = $this->_getQuote($quoteId, $store);
109
  if (empty($store)) {
144
  }
145
 
146
  try {
147
+ $quote->collectTotals()->save();
148
+ } catch (Exception $e) {
149
  $this->_fault("update_product_quote_save_fault", $e->getMessage());
150
  }
151
 
158
  * @param $store
159
  * @return bool
160
  */
161
+ public function remove($quoteId, $productsData, $store = null)
162
  {
163
  $quote = $this->_getQuote($quoteId, $store);
164
  if (empty($store)) {
200
  }
201
 
202
  try {
203
+ $quote->collectTotals()->save();
204
+ } catch (Exception $e) {
205
  $this->_fault("remove_product_quote_save_fault", $e->getMessage());
206
  }
207
 
248
  * @param $store
249
  * @return bool
250
  */
251
+ public function moveToCustomerQuote($quoteId, $productsData, $store = null)
252
  {
253
  $quote = $this->_getQuote($quoteId, $store);
254
 
280
  }
281
 
282
  $errors = array();
283
+ foreach ($productsData as $key => $productItem) {
284
  if (isset($productItem['product_id'])) {
285
  $productByItem = $this->_getProduct($productItem['product_id'], $store, "id");
286
  } else if (isset($productItem['sku'])) {
294
  /** @var $quoteItem Mage_Sales_Model_Quote_Item */
295
  $quoteItem = $this->_getQuoteItemByProduct($quote, $productByItem,
296
  $this->_getProductRequest($productItem));
297
+ if ($quoteItem && $quoteItem->getId()) {
298
  $newQuoteItem = clone $quoteItem;
299
  $newQuoteItem->setId(null);
300
  $customerQuote->addItem($newQuoteItem);
app/code/core/Mage/Checkout/controllers/CartController.php CHANGED
@@ -397,6 +397,11 @@ class Mage_Checkout_CartController extends Mage_Core_Controller_Front_Action
397
  */
398
  public function updatePostAction()
399
  {
 
 
 
 
 
400
  $updateAction = (string)$this->getRequest()->getParam('update_cart_action');
401
 
402
  switch ($updateAction) {
397
  */
398
  public function updatePostAction()
399
  {
400
+ if (!$this->_validateFormKey()) {
401
+ $this->_redirect('*/*/');
402
+ return;
403
+ }
404
+
405
  $updateAction = (string)$this->getRequest()->getParam('update_cart_action');
406
 
407
  switch ($updateAction) {
app/code/core/Mage/Checkout/controllers/MultishippingController.php CHANGED
@@ -267,6 +267,9 @@ class Mage_Checkout_MultishippingController extends Mage_Checkout_Controller_Act
267
  }
268
  }
269
 
 
 
 
270
  public function backToAddressesAction()
271
  {
272
  $this->_getState()->setActiveStep(
@@ -292,6 +295,11 @@ class Mage_Checkout_MultishippingController extends Mage_Checkout_Controller_Act
292
  $this->_redirect('*/*/addresses');
293
  }
294
 
 
 
 
 
 
295
  protected function _validateMinimumAmount()
296
  {
297
  if (!$this->_getCheckout()->validateMinimumAmount()) {
@@ -326,6 +334,9 @@ class Mage_Checkout_MultishippingController extends Mage_Checkout_Controller_Act
326
  $this->renderLayout();
327
  }
328
 
 
 
 
329
  public function backToShippingAction()
330
  {
331
  $this->_getState()->setActiveStep(
@@ -337,6 +348,9 @@ class Mage_Checkout_MultishippingController extends Mage_Checkout_Controller_Act
337
  $this->_redirect('*/*/shipping');
338
  }
339
 
 
 
 
340
  public function shippingPostAction()
341
  {
342
  $shippingMethods = $this->getRequest()->getPost('shipping_method');
@@ -354,7 +368,7 @@ class Mage_Checkout_MultishippingController extends Mage_Checkout_Controller_Act
354
  );
355
  $this->_redirect('*/*/billing');
356
  }
357
- catch (Exception $e){
358
  $this->_getCheckoutSession()->addError($e->getMessage());
359
  $this->_redirect('*/*/shipping');
360
  }
@@ -402,6 +416,9 @@ class Mage_Checkout_MultishippingController extends Mage_Checkout_Controller_Act
402
  return true;
403
  }
404
 
 
 
 
405
  public function backToBillingAction()
406
  {
407
  $this->_getState()->setActiveStep(
@@ -453,8 +470,16 @@ class Mage_Checkout_MultishippingController extends Mage_Checkout_Controller_Act
453
  }
454
  }
455
 
 
 
 
456
  public function overviewPostAction()
457
  {
 
 
 
 
 
458
  if (!$this->_validateMinimumAmount()) {
459
  return;
460
  }
@@ -489,7 +514,7 @@ class Mage_Checkout_MultishippingController extends Mage_Checkout_Controller_Act
489
  $this->_redirect('*/*/success');
490
  } catch (Mage_Payment_Model_Info_Exception $e) {
491
  $message = $e->getMessage();
492
- if( !empty($message) ) {
493
  $this->_getCheckoutSession()->addError($message);
494
  }
495
  $this->_redirect('*/*/billing');
@@ -500,12 +525,12 @@ class Mage_Checkout_MultishippingController extends Mage_Checkout_Controller_Act
500
  $this->_getCheckoutSession()->addError($e->getMessage());
501
  $this->_redirect('*/cart');
502
  }
503
- catch (Mage_Core_Exception $e){
504
  Mage::helper('checkout')
505
  ->sendPaymentFailedEmail($this->_getCheckout()->getQuote(), $e->getMessage(), 'multi-shipping');
506
  $this->_getCheckoutSession()->addError($e->getMessage());
507
  $this->_redirect('*/*/billing');
508
- } catch (Exception $e){
509
  Mage::logException($e);
510
  Mage::helper('checkout')
511
  ->sendPaymentFailedEmail($this->_getCheckout()->getQuote(), $e->getMessage(), 'multi-shipping');
@@ -515,7 +540,7 @@ class Mage_Checkout_MultishippingController extends Mage_Checkout_Controller_Act
515
  }
516
 
517
  /**
518
- * Multishipping checkout succes page
519
  */
520
  public function successAction()
521
  {
@@ -533,7 +558,6 @@ class Mage_Checkout_MultishippingController extends Mage_Checkout_Controller_Act
533
 
534
  /**
535
  * Redirect to login page
536
- *
537
  */
538