PageRenderTime 53ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/app/code/core/Mage/Catalog/Model/Api2/Product/Rest.php

https://github.com/FiveDigital/magento2
PHP | 401 lines | 216 code | 30 blank | 155 comment | 41 complexity | cc65e31fa08ffd1415f23275fe11bc65 MD5 | raw file
Possible License(s): CC-BY-SA-3.0
  1. <?php
  2. /**
  3. * Magento
  4. *
  5. * NOTICE OF LICENSE
  6. *
  7. * This source file is subject to the Open Software License (OSL 3.0)
  8. * that is bundled with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://opensource.org/licenses/osl-3.0.php
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@magentocommerce.com so we can send you a copy immediately.
  14. *
  15. * DISCLAIMER
  16. *
  17. * Do not edit or add to this file if you wish to upgrade Magento to newer
  18. * versions in the future. If you wish to customize Magento for your
  19. * needs please refer to http://www.magentocommerce.com for more information.
  20. *
  21. * @category Mage
  22. * @package Mage_Catalog
  23. * @copyright Copyright (c) 2012 Magento Inc. (http://www.magentocommerce.com)
  24. * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
  25. */
  26. /**
  27. * Abstract API2 class for product instance
  28. *
  29. * @category Mage
  30. * @package Mage_Catalog
  31. * @author Magento Core Team <core@magentocommerce.com>
  32. */
  33. abstract class Mage_Catalog_Model_Api2_Product_Rest extends Mage_Catalog_Model_Api2_Product
  34. {
  35. /**
  36. * Current loaded product
  37. *
  38. * @var Mage_Catalog_Model_Product
  39. */
  40. protected $_product;
  41. /**
  42. * Retrieve product data
  43. *
  44. * @return array
  45. */
  46. protected function _retrieve()
  47. {
  48. $product = $this->_getProduct();
  49. $this->_prepareProductForResponse($product);
  50. return $product->getData();
  51. }
  52. /**
  53. * Retrieve list of products
  54. *
  55. * @return array
  56. */
  57. protected function _retrieveCollection()
  58. {
  59. /** @var $collection Mage_Catalog_Model_Resource_Product_Collection */
  60. $collection = Mage::getResourceModel('Mage_Catalog_Model_Resource_Product_Collection');
  61. $store = $this->_getStore();
  62. $entityOnlyAttributes = $this->getEntityOnlyAttributes($this->getUserType(),
  63. Mage_Api2_Model_Resource::OPERATION_ATTRIBUTE_READ);
  64. $availableAttributes = array_keys($this->getAvailableAttributes($this->getUserType(),
  65. Mage_Api2_Model_Resource::OPERATION_ATTRIBUTE_READ));
  66. // available attributes not contain image attribute, but it needed for get image_url
  67. $availableAttributes[] = 'image';
  68. $collection->addStoreFilter($store->getId())
  69. ->addPriceData($this->_getCustomerGroupId(), $store->getWebsiteId())
  70. ->addAttributeToSelect(array_diff($availableAttributes, $entityOnlyAttributes))
  71. ->addAttributeToFilter('visibility', array(
  72. 'neq' => Mage_Catalog_Model_Product_Visibility::VISIBILITY_NOT_VISIBLE))
  73. ->addAttributeToFilter('status', array('eq' => Mage_Catalog_Model_Product_Status::STATUS_ENABLED));
  74. $this->_applyCategoryFilter($collection);
  75. $this->_applyCollectionModifiers($collection);
  76. $products = $collection->load();
  77. /** @var Mage_Catalog_Model_Product $product */
  78. foreach ($products as $product) {
  79. $this->_setProduct($product);
  80. $this->_prepareProductForResponse($product);
  81. }
  82. return $products->toArray();
  83. }
  84. /**
  85. * Apply filter by category id
  86. *
  87. * @param Mage_Catalog_Model_Resource_Product_Collection $collection
  88. */
  89. protected function _applyCategoryFilter(Mage_Catalog_Model_Resource_Product_Collection $collection)
  90. {
  91. $categoryId = $this->getRequest()->getParam('category_id');
  92. if ($categoryId) {
  93. $category = $this->_getCategoryById($categoryId);
  94. if (!$category->getId()) {
  95. $this->_critical('Category not found.', Mage_Api2_Model_Server::HTTP_BAD_REQUEST);
  96. }
  97. $collection->addCategoryFilter($category);
  98. }
  99. }
  100. /**
  101. * Add special fields to product get response
  102. *
  103. * @param Mage_Catalog_Model_Product $product
  104. */
  105. protected function _prepareProductForResponse(Mage_Catalog_Model_Product $product)
  106. {
  107. /** @var $productHelper Mage_Catalog_Helper_Product */
  108. $productHelper = Mage::helper('Mage_Catalog_Helper_Product');
  109. $productData = $product->getData();
  110. $product->setWebsiteId($this->_getStore()->getWebsiteId());
  111. // customer group is required in product for correct prices calculation
  112. $product->setCustomerGroupId($this->_getCustomerGroupId());
  113. // calculate prices
  114. $finalPrice = $product->getFinalPrice();
  115. $productData['regular_price_with_tax'] = $this->_applyTaxToPrice($product->getPrice(), true);
  116. $productData['regular_price_without_tax'] = $this->_applyTaxToPrice($product->getPrice(), false);
  117. $productData['final_price_with_tax'] = $this->_applyTaxToPrice($finalPrice, true);
  118. $productData['final_price_without_tax'] = $this->_applyTaxToPrice($finalPrice, false);
  119. $productData['is_saleable'] = $product->getIsSalable();
  120. $productData['image_url'] = (string) Mage::helper('Mage_Catalog_Helper_Image')->init($product, 'image');
  121. if ($this->getActionType() == self::ACTION_TYPE_ENTITY) {
  122. // define URLs
  123. $productData['url'] = $productHelper->getProductUrl($product->getId());
  124. /** @var $cartHelper Mage_Checkout_Helper_Cart */
  125. $cartHelper = Mage::helper('Mage_Checkout_Helper_Cart');
  126. $productData['buy_now_url'] = $cartHelper->getAddUrl($product);
  127. /** @var $stockItem Mage_CatalogInventory_Model_Stock_Item */
  128. $stockItem = $product->getStockItem();
  129. if (!$stockItem) {
  130. $stockItem = Mage::getModel('Mage_CatalogInventory_Model_Stock_Item');
  131. $stockItem->loadByProduct($product);
  132. }
  133. $productData['is_in_stock'] = $stockItem->getIsInStock();
  134. /** @var $reviewModel Mage_Review_Model_Review */
  135. $reviewModel = Mage::getModel('Mage_Review_Model_Review');
  136. $productData['total_reviews_count'] = $reviewModel->getTotalReviews($product->getId(), true,
  137. $this->_getStore()->getId());
  138. $productData['tier_price'] = $this->_getTierPrices();
  139. $productData['has_custom_options'] = count($product->getOptions()) > 0;
  140. } else {
  141. // remove tier price from response
  142. $product->unsetData('tier_price');
  143. unset($productData['tier_price']);
  144. }
  145. $product->addData($productData);
  146. }
  147. /**
  148. * Product create only available for admin
  149. *
  150. * @param array $data
  151. */
  152. protected function _create(array $data)
  153. {
  154. $this->_critical(self::RESOURCE_METHOD_NOT_ALLOWED);
  155. }
  156. /**
  157. * Product update only available for admin
  158. *
  159. * @param array $data
  160. */
  161. protected function _update(array $data)
  162. {
  163. $this->_critical(self::RESOURCE_METHOD_NOT_ALLOWED);
  164. }
  165. /**
  166. * Product delete only available for admin
  167. */
  168. protected function _delete()
  169. {
  170. $this->_critical(self::RESOURCE_METHOD_NOT_ALLOWED);
  171. }
  172. /**
  173. * Load product by its SKU or ID provided in request
  174. *
  175. * @return Mage_Catalog_Model_Product
  176. */
  177. protected function _getProduct()
  178. {
  179. if (is_null($this->_product)) {
  180. $productId = $this->getRequest()->getParam('id');
  181. /** @var $productHelper Mage_Catalog_Helper_Product */
  182. $productHelper = Mage::helper('Mage_Catalog_Helper_Product');
  183. $product = $productHelper->getProduct($productId, $this->_getStore()->getId());
  184. if (!($product->getId())) {
  185. $this->_critical(self::RESOURCE_NOT_FOUND);
  186. }
  187. // check if product belongs to website current
  188. if ($this->_getStore()->getId()) {
  189. $isValidWebsite = in_array($this->_getStore()->getWebsiteId(), $product->getWebsiteIds());
  190. if (!$isValidWebsite) {
  191. $this->_critical(self::RESOURCE_NOT_FOUND);
  192. }
  193. }
  194. // Check display settings for customers & guests
  195. if ($this->getApiUser()->getType() != Mage_Api2_Model_Auth_User_Admin::USER_TYPE) {
  196. // check if product assigned to any website and can be shown
  197. if ((!Mage::app()->hasSingleStore() && !count($product->getWebsiteIds()))
  198. || !$productHelper->canShow($product)
  199. ) {
  200. $this->_critical(self::RESOURCE_NOT_FOUND);
  201. }
  202. }
  203. $this->_product = $product;
  204. }
  205. return $this->_product;
  206. }
  207. /**
  208. * Set product
  209. *
  210. * @param Mage_Catalog_Model_Product $product
  211. */
  212. protected function _setProduct(Mage_Catalog_Model_Product $product)
  213. {
  214. $this->_product = $product;
  215. }
  216. /**
  217. * Load category by id
  218. *
  219. * @param int $categoryId
  220. * @return Mage_Catalog_Model_Category
  221. */
  222. protected function _getCategoryById($categoryId)
  223. {
  224. return Mage::getModel('Mage_Catalog_Model_Category')->load($categoryId);
  225. }
  226. /**
  227. * Get product price with all tax settings processing
  228. *
  229. * @param float $price inputed product price
  230. * @param bool $includingTax return price include tax flag
  231. * @param null|Mage_Customer_Model_Address $shippingAddress
  232. * @param null|Mage_Customer_Model_Address $billingAddress
  233. * @param null|int $ctc customer tax class
  234. * @param bool $priceIncludesTax flag that price parameter contain tax
  235. * @return float
  236. * @see Mage_Tax_Helper_Data::getPrice()
  237. */
  238. protected function _getPrice($price, $includingTax = null, $shippingAddress = null,
  239. $billingAddress = null, $ctc = null, $priceIncludesTax = null
  240. ) {
  241. $product = $this->_getProduct();
  242. $store = $this->_getStore();
  243. if (is_null($priceIncludesTax)) {
  244. /** @var $config Mage_Tax_Model_Config */
  245. $config = Mage::getSingleton('Mage_Tax_Model_Config');
  246. $priceIncludesTax = $config->priceIncludesTax($store) || $config->getNeedUseShippingExcludeTax();
  247. }
  248. $percent = $product->getTaxPercent();
  249. $includingPercent = null;
  250. $taxClassId = $product->getTaxClassId();
  251. if (is_null($percent)) {
  252. if ($taxClassId) {
  253. $request = Mage::getSingleton('Mage_Tax_Model_Calculation')
  254. ->getRateRequest($shippingAddress, $billingAddress, $ctc, $store);
  255. $percent = Mage::getSingleton('Mage_Tax_Model_Calculation')->getRate($request->setProductClassId($taxClassId));
  256. }
  257. }
  258. if ($taxClassId && $priceIncludesTax) {
  259. $request = Mage::getSingleton('Mage_Tax_Model_Calculation')->getRateRequest(false, false, false, $store);
  260. $includingPercent = Mage::getSingleton('Mage_Tax_Model_Calculation')
  261. ->getRate($request->setProductClassId($taxClassId));
  262. }
  263. if ($percent === false || is_null($percent)) {
  264. if ($priceIncludesTax && !$includingPercent) {
  265. return $price;
  266. }
  267. }
  268. $product->setTaxPercent($percent);
  269. if (!is_null($includingTax)) {
  270. if ($priceIncludesTax) {
  271. if ($includingTax) {
  272. /**
  273. * Recalculate price include tax in case of different rates
  274. */
  275. if ($includingPercent != $percent) {
  276. $price = $this->_calculatePrice($price, $includingPercent, false);
  277. /**
  278. * Using regular rounding. Ex:
  279. * price incl tax = 52.76
  280. * store tax rate = 19.6%
  281. * customer tax rate= 19%
  282. *
  283. * price excl tax = 52.76 / 1.196 = 44.11371237 ~ 44.11
  284. * tax = 44.11371237 * 0.19 = 8.381605351 ~ 8.38
  285. * price incl tax = 52.49531773 ~ 52.50 != 52.49
  286. *
  287. * that why we need round prices excluding tax before applying tax
  288. * this calculation is used for showing prices on catalog pages
  289. */
  290. if ($percent != 0) {
  291. $price = Mage::getSingleton('Mage_Tax_Model_Calculation')->round($price);
  292. $price = $this->_calculatePrice($price, $percent, true);
  293. }
  294. }
  295. } else {
  296. $price = $this->_calculatePrice($price, $includingPercent, false);
  297. }
  298. } else {
  299. if ($includingTax) {
  300. $price = $this->_calculatePrice($price, $percent, true);
  301. }
  302. }
  303. } else {
  304. if ($priceIncludesTax) {
  305. if ($includingTax) {
  306. $price = $this->_calculatePrice($price, $includingPercent, false);
  307. $price = $this->_calculatePrice($price, $percent, true);
  308. } else {
  309. $price = $this->_calculatePrice($price, $includingPercent, false);
  310. }
  311. } else {
  312. if ($includingTax) {
  313. $price = $this->_calculatePrice($price, $percent, true);
  314. }
  315. }
  316. }
  317. return $store->roundPrice($price);
  318. }
  319. /**
  320. * Calculate price imcluding/excluding tax base on tax rate percent
  321. *
  322. * @param float $price
  323. * @param float $percent
  324. * @param bool $includeTax true - for calculate price including tax and false if price excluding tax
  325. * @return float
  326. */
  327. protected function _calculatePrice($price, $percent, $includeTax)
  328. {
  329. /** @var $calculator Mage_Tax_Model_Calculation */
  330. $calculator = Mage::getSingleton('Mage_Tax_Model_Calculation');
  331. $taxAmount = $calculator->calcTaxAmount($price, $percent, !$includeTax, false);
  332. return $includeTax ? $price + $taxAmount : $price - $taxAmount;
  333. }
  334. /**
  335. * Retrive tier prices in special format
  336. *
  337. * @return array
  338. */
  339. protected function _getTierPrices()
  340. {
  341. $tierPrices = array();
  342. foreach ($this->_getProduct()->getTierPrice() as $tierPrice) {
  343. $tierPrices[] = array(
  344. 'qty' => $tierPrice['price_qty'],
  345. 'price_with_tax' => $this->_applyTaxToPrice($tierPrice['price']),
  346. 'price_without_tax' => $this->_applyTaxToPrice($tierPrice['price'], false)
  347. );
  348. }
  349. return $tierPrices;
  350. }
  351. /**
  352. * Default implementation. May be different for customer/guest/admin role.
  353. *
  354. * @return null
  355. */
  356. protected function _getCustomerGroupId()
  357. {
  358. return null;
  359. }
  360. /**
  361. * Default implementation. May be different for customer/guest/admin role.
  362. *
  363. * @param float $price
  364. * @param bool $withTax
  365. * @return float
  366. */
  367. protected function _applyTaxToPrice($price, $withTax = true)
  368. {
  369. return $price;
  370. }
  371. }