Guest User

Untitled

a guest
May 5th, 2014
214
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  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) 2013 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.  
  28. /**
  29. * Product collection
  30. *
  31. * @category Mage
  32. * @package Mage_Catalog
  33. * @author Magento Core Team <core@magentocommerce.com>
  34. */
  35. class Mage_Catalog_Model_Resource_Product_Collection extends Mage_Catalog_Model_Resource_Collection_Abstract
  36. {
  37. /**
  38. * Alias for index table
  39. */
  40. const INDEX_TABLE_ALIAS = 'price_index';
  41.  
  42. /**
  43. * Alias for main table
  44. */
  45. const MAIN_TABLE_ALIAS = 'e';
  46.  
  47. /**
  48. * Catalog Product Flat is enabled cache per store
  49. *
  50. * @var array
  51. */
  52. protected $_flatEnabled = array();
  53.  
  54. /**
  55. * Product websites table name
  56. *
  57. * @var string
  58. */
  59. protected $_productWebsiteTable;
  60.  
  61. /**
  62. * Product categories table name
  63. *
  64. * @var string
  65. */
  66. protected $_productCategoryTable;
  67.  
  68. /**
  69. * Is add URL rewrites to collection flag
  70. *
  71. * @var bool
  72. */
  73. protected $_addUrlRewrite = false;
  74.  
  75. /**
  76. * Add URL rewrite for category
  77. *
  78. * @var int
  79. */
  80. protected $_urlRewriteCategory = '';
  81.  
  82. /**
  83. * Is add minimal price to product collection flag
  84. *
  85. * @var bool
  86. */
  87. protected $_addMinimalPrice = false;
  88.  
  89. /**
  90. * Is add final price to product collection flag
  91. *
  92. * @var unknown_type
  93. */
  94. protected $_addFinalPrice = false;
  95.  
  96. /**
  97. * Cache for all ids
  98. *
  99. * @var array
  100. */
  101. protected $_allIdsCache = null;
  102.  
  103. /**
  104. * Is add tax percents to product collection flag
  105. *
  106. * @var bool
  107. */
  108. protected $_addTaxPercents = false;
  109.  
  110. /**
  111. * Product limitation filters
  112. * Allowed filters
  113. * store_id int;
  114. * category_id int;
  115. * category_is_anchor int;
  116. * visibility array|int;
  117. * website_ids array|int;
  118. * store_table string;
  119. * use_price_index bool; join price index table flag
  120. * customer_group_id int; required for price; customer group limitation for price
  121. * website_id int; required for price; website limitation for price
  122. *
  123. * @var array
  124. */
  125. protected $_productLimitationFilters = array();
  126.  
  127. /**
  128. * Category product count select
  129. *
  130. * @var Zend_Db_Select
  131. */
  132. protected $_productCountSelect = null;
  133.  
  134. /**
  135. * Enter description here ...
  136. *
  137. * @var bool
  138. */
  139. protected $_isWebsiteFilter = false;
  140.  
  141. /**
  142. * Additional field filters, applied in _productLimitationJoinPrice()
  143. *
  144. * @var array
  145. */
  146. protected $_priceDataFieldFilters = array();
  147.  
  148. /**
  149. * Map of price fields
  150. *
  151. * @var array
  152. */
  153. protected $_map = array('fields' => array(
  154. 'price' => 'price_index.price',
  155. 'final_price' => 'price_index.final_price',
  156. 'min_price' => 'price_index.min_price',
  157. 'max_price' => 'price_index.max_price',
  158. 'tier_price' => 'price_index.tier_price',
  159. 'special_price' => 'price_index.special_price',
  160. ));
  161.  
  162. /**
  163. * Price expression sql
  164. *
  165. * @var string|null
  166. */
  167. protected $_priceExpression;
  168.  
  169. /**
  170. * Additional price expression sql part
  171. *
  172. * @var string|null
  173. */
  174. protected $_additionalPriceExpression;
  175.  
  176. /**
  177. * Max prise (statistics data)
  178. *
  179. * @var float
  180. */
  181. protected $_maxPrice;
  182.  
  183. /**
  184. * Min prise (statistics data)
  185. *
  186. * @var float
  187. */
  188. protected $_minPrice;
  189.  
  190. /**
  191. * Prise standard deviation (statistics data)
  192. *
  193. * @var float
  194. */
  195. protected $_priceStandardDeviation;
  196.  
  197. /**
  198. * Prises count (statistics data)
  199. *
  200. * @var int
  201. */
  202. protected $_pricesCount = null;
  203.  
  204. /**
  205. * Cloned Select after dispatching 'catalog_prepare_price_select' event
  206. *
  207. * @var Varien_Db_Select
  208. */
  209. protected $_catalogPreparePriceSelect = null;
  210.  
  211. /**
  212. * Catalog factory instance
  213. *
  214. * @var Mage_Catalog_Model_Factory
  215. */
  216. protected $_factory;
  217.  
  218. /**
  219. * Initialize factory
  220. *
  221. * @param Mage_Core_Model_Resource_Abstract $resource
  222. * @param array $args
  223. */
  224. public function __construct($resource = null, array $args = array())
  225. {
  226. parent::__construct($resource);
  227. $this->_factory = !empty($args['factory']) ? $args['factory'] : Mage::getSingleton('catalog/factory');
  228. }
  229.  
  230. /**
  231. * Get cloned Select after dispatching 'catalog_prepare_price_select' event
  232. *
  233. * @return Varien_Db_Select
  234. */
  235. public function getCatalogPreparedSelect()
  236. {
  237. return $this->_catalogPreparePriceSelect;
  238. }
  239.  
  240. /**
  241. * Prepare additional price expression sql part
  242. *
  243. * @param Varien_Db_Select $select
  244. * @return Mage_Catalog_Model_Resource_Product_Collection
  245. */
  246. protected function _preparePriceExpressionParameters($select)
  247. {
  248. // prepare response object for event
  249. $response = new Varien_Object();
  250. $response->setAdditionalCalculations(array());
  251. $tableAliases = array_keys($select->getPart(Zend_Db_Select::FROM));
  252. if (in_array(self::INDEX_TABLE_ALIAS, $tableAliases)) {
  253. $table = self::INDEX_TABLE_ALIAS;
  254. } else {
  255. $table = reset($tableAliases);
  256. }
  257.  
  258. // prepare event arguments
  259. $eventArgs = array(
  260. 'select' => $select,
  261. 'table' => $table,
  262. 'store_id' => $this->getStoreId(),
  263. 'response_object' => $response
  264. );
  265.  
  266. Mage::dispatchEvent('catalog_prepare_price_select', $eventArgs);
  267.  
  268. $additional = join('', $response->getAdditionalCalculations());
  269. $this->_priceExpression = $table . '.min_price';
  270. $this->_additionalPriceExpression = $additional;
  271. $this->_catalogPreparePriceSelect = clone $select;
  272.  
  273. return $this;
  274. }
  275.  
  276. /**
  277. * Get price expression sql part
  278. *
  279. * @param Varien_Db_Select $select
  280. * @return string
  281. */
  282. public function getPriceExpression($select)
  283. {
  284. if (is_null($this->_priceExpression)) {
  285. $this->_preparePriceExpressionParameters($select);
  286. }
  287. return $this->_priceExpression;
  288. }
  289.  
  290. /**
  291. * Get additional price expression sql part
  292. *
  293. * @param Varien_Db_Select $select
  294. * @return string
  295. */
  296. public function getAdditionalPriceExpression($select)
  297. {
  298. if (is_null($this->_additionalPriceExpression)) {
  299. $this->_preparePriceExpressionParameters($select);
  300. }
  301. return $this->_additionalPriceExpression;
  302. }
  303.  
  304. /**
  305. * Get currency rate
  306. *
  307. * @return float
  308. */
  309. public function getCurrencyRate()
  310. {
  311. return Mage::app()->getStore($this->getStoreId())->getCurrentCurrencyRate();
  312. }
  313.  
  314. /**
  315. * Retrieve Catalog Product Flat Helper object
  316. *
  317. * @return Mage_Catalog_Helper_Product_Flat
  318. */
  319. public function getFlatHelper()
  320. {
  321. return Mage::helper('catalog/product_flat');
  322. }
  323.  
  324. /**
  325. * Retrieve is flat enabled flag
  326. * Return always false if magento run admin
  327. *
  328. * @return bool
  329. */
  330. public function isEnabledFlat()
  331. {
  332. // Flat Data can be used only on frontend
  333. if (Mage::app()->getStore()->isAdmin()) {
  334. return false;
  335. }
  336. $storeId = $this->getStoreId();
  337. if (!isset($this->_flatEnabled[$storeId])) {
  338. $flatHelper = $this->getFlatHelper();
  339. $this->_flatEnabled[$storeId] = $flatHelper->isAvailable() && $flatHelper->isBuilt($storeId);
  340. }
  341. return $this->_flatEnabled[$storeId];
  342. }
  343.  
  344. /**
  345. * Initialize resources
  346. *
  347. */
  348. protected function _construct()
  349. {
  350. if ($this->isEnabledFlat()) {
  351. $this->_init('catalog/product', 'catalog/product_flat');
  352. }
  353. else {
  354. $this->_init('catalog/product');
  355. }
  356. $this->_initTables();
  357. }
  358.  
  359. /**
  360. * Define product website and category product tables
  361. *
  362. */
  363. protected function _initTables()
  364. {
  365. $this->_productWebsiteTable = $this->getResource()->getTable('catalog/product_website');
  366. $this->_productCategoryTable= $this->getResource()->getTable('catalog/category_product');
  367. }
  368.  
  369. /**
  370. * Standard resource collection initalization
  371. *
  372. * @param string $model
  373. * @param unknown_type $entityModel
  374. * @return Mage_Catalog_Model_Resource_Product_Collection
  375. */
  376. protected function _init($model, $entityModel = null)
  377. {
  378. if ($this->isEnabledFlat()) {
  379. $entityModel = 'catalog/product_flat';
  380. }
  381.  
  382. return parent::_init($model, $entityModel);
  383. }
  384.  
  385. /**
  386. * Prepare static entity fields
  387. *
  388. * @return Mage_Catalog_Model_Resource_Product_Collection
  389. */
  390. protected function _prepareStaticFields()
  391. {
  392. if ($this->isEnabledFlat()) {
  393. return $this;
  394. }
  395. return parent::_prepareStaticFields();
  396. }
  397.  
  398. /**
  399. * Retrieve collection empty item
  400. * Redeclared for specifying id field name without getting resource model inside model
  401. *
  402. * @return Varien_Object
  403. */
  404. public function getNewEmptyItem()
  405. {
  406. $object = parent::getNewEmptyItem();
  407. if ($this->isEnabledFlat()) {
  408. $object->setIdFieldName($this->getEntity()->getIdFieldName());
  409. }
  410. return $object;
  411. }
  412.  
  413. /**
  414. * Set entity to use for attributes
  415. *
  416. * @param Mage_Eav_Model_Entity_Abstract $entity
  417. * @return Mage_Catalog_Model_Resource_Product_Collection
  418. */
  419. public function setEntity($entity)
  420. {
  421. if ($this->isEnabledFlat() && ($entity instanceof Mage_Core_Model_Resource_Db_Abstract)) {
  422. $this->_entity = $entity;
  423. return $this;
  424. }
  425. return parent::setEntity($entity);
  426. }
  427.  
  428. /**
  429. * Set Store scope for collection
  430. *
  431. * @param mixed $store
  432. * @return Mage_Catalog_Model_Resource_Product_Collection
  433. */
  434. public function setStore($store)
  435. {
  436. parent::setStore($store);
  437. if ($this->isEnabledFlat()) {
  438. $this->getEntity()->setStoreId($this->getStoreId());
  439. }
  440. return $this;
  441. }
  442.  
  443. /**
  444. * Initialize collection select
  445. * Redeclared for remove entity_type_id condition
  446. * in catalog_product_entity we store just products
  447. *
  448. * @return Mage_Catalog_Model_Resource_Product_Collection
  449. */
  450. protected function _initSelect()
  451. {
  452. if ($this->isEnabledFlat()) {
  453. $this->getSelect()
  454. ->from(array(self::MAIN_TABLE_ALIAS => $this->getEntity()->getFlatTableName()), null)
  455. ->columns(array('status' => new Zend_Db_Expr(Mage_Catalog_Model_Product_Status::STATUS_ENABLED)));
  456. $this->addAttributeToSelect(array('entity_id', 'type_id', 'attribute_set_id'));
  457. if ($this->getFlatHelper()->isAddChildData()) {
  458. $this->getSelect()
  459. ->where('e.is_child=?', 0);
  460. $this->addAttributeToSelect(array('child_id', 'is_child'));
  461. }
  462. } else {
  463. $this->getSelect()->from(array(self::MAIN_TABLE_ALIAS => $this->getEntity()->getEntityTable()));
  464. }
  465. return $this;
  466. }
  467.  
  468. /**
  469. * Load attributes into loaded entities
  470. *
  471. * @param bool $printQuery
  472. * @param bool $logQuery
  473. * @return Mage_Catalog_Model_Resource_Product_Collection
  474. */
  475. public function _loadAttributes($printQuery = false, $logQuery = false)
  476. {
  477. if ($this->isEnabledFlat()) {
  478. return $this;
  479. }
  480. return parent::_loadAttributes($printQuery, $logQuery);
  481. }
  482.  
  483. /**
  484. * Add attribute to entities in collection
  485. * If $attribute=='*' select all attributes
  486. *
  487. * @param array|string|integer|Mage_Core_Model_Config_Element $attribute
  488. * @param false|string $joinType
  489. * @return Mage_Catalog_Model_Resource_Product_Collection
  490. */
  491. public function addAttributeToSelect($attribute, $joinType = false)
  492. {
  493. if ($this->isEnabledFlat()) {
  494. if (!is_array($attribute)) {
  495. $attribute = array($attribute);
  496. }
  497. foreach ($attribute as $attributeCode) {
  498. if ($attributeCode == '*') {
  499. foreach ($this->getEntity()->getAllTableColumns() as $column) {
  500. $this->getSelect()->columns('e.' . $column);
  501. $this->_selectAttributes[$column] = $column;
  502. $this->_staticFields[$column] = $column;
  503. }
  504. } else {
  505. $columns = $this->getEntity()->getAttributeForSelect($attributeCode);
  506. if ($columns) {
  507. foreach ($columns as $alias => $column) {
  508. $this->getSelect()->columns(array($alias => 'e.' . $column));
  509. $this->_selectAttributes[$column] = $column;
  510. $this->_staticFields[$column] = $column;
  511. }
  512. }
  513. }
  514. }
  515. return $this;
  516. }
  517. return parent::addAttributeToSelect($attribute, $joinType);
  518. }
  519.  
  520. /**
  521. * Add tax class id attribute to select and join price rules data if needed
  522. *
  523. * @return Mage_Catalog_Model_Resource_Product_Collection
  524. */
  525. protected function _beforeLoad()
  526. {
  527. Mage::dispatchEvent('catalog_product_collection_load_before', array('collection' => $this));
  528.  
  529. return parent::_beforeLoad();
  530. }
  531.  
  532. /**
  533. * Processing collection items after loading
  534. * Adding url rewrites, minimal prices, final prices, tax percents
  535. *
  536. * @return Mage_Catalog_Model_Resource_Product_Collection
  537. */
  538. protected function _afterLoad()
  539. {
  540. if ($this->_addUrlRewrite) {
  541. $this->_addUrlRewrite($this->_urlRewriteCategory);
  542. }
  543.  
  544. if (count($this) > 0) {
  545. Mage::dispatchEvent('catalog_product_collection_load_after', array('collection' => $this));
  546. }
  547.  
  548. foreach ($this as $product) {
  549. if ($product->isRecurring() && $profile = $product->getRecurringProfile()) {
  550. $product->setRecurringProfile(unserialize($profile));
  551. }
  552. }
  553.  
  554. return $this;
  555. }
  556.  
  557. /**
  558. * Prepare Url Data object
  559. *
  560. * @return Mage_Catalog_Model_Resource_Product_Collection
  561. * @deprecated after 1.7.0.2
  562. */
  563. protected function _prepareUrlDataObject()
  564. {
  565. $objects = array();
  566. /** @var $item Mage_Catalog_Model_Product */
  567. foreach ($this->_items as $item) {
  568. if ($this->getFlag('do_not_use_category_id')) {
  569. $item->setDoNotUseCategoryId(true);
  570. }
  571. if (!$item->isVisibleInSiteVisibility() && $item->getItemStoreId()) {
  572. $objects[$item->getEntityId()] = $item->getItemStoreId();
  573. }
  574. }
  575.  
  576. if ($objects && $this->hasFlag('url_data_object')) {
  577. $objects = Mage::getResourceSingleton('catalog/url')
  578. ->getRewriteByProductStore($objects);
  579. foreach ($this->_items as $item) {
  580. if (isset($objects[$item->getEntityId()])) {
  581. $object = new Varien_Object($objects[$item->getEntityId()]);
  582. $item->setUrlDataObject($object);
  583. }
  584. }
  585. }
  586.  
  587. return $this;
  588. }
  589.  
  590. /**
  591. * Add collection filters by identifiers
  592. *
  593. * @param mixed $productId
  594. * @param boolean $exclude
  595. * @return Mage_Catalog_Model_Resource_Product_Collection
  596. */
  597. public function addIdFilter($productId, $exclude = false)
  598. {
  599. if (empty($productId)) {
  600. $this->_setIsLoaded(true);
  601. return $this;
  602. }
  603. if (is_array($productId)) {
  604. if (!empty($productId)) {
  605. if ($exclude) {
  606. $condition = array('nin' => $productId);
  607. } else {
  608. $condition = array('in' => $productId);
  609. }
  610. } else {
  611. $condition = '';
  612. }
  613. } else {
  614. if ($exclude) {
  615. $condition = array('neq' => $productId);
  616. } else {
  617. $condition = $productId;
  618. }
  619. }
  620. $this->addFieldToFilter('entity_id', $condition);
  621. return $this;
  622. }
  623.  
  624. /**
  625. * Adding product website names to result collection
  626. * Add for each product websites information
  627. *
  628. * @return Mage_Catalog_Model_Resource_Product_Collection
  629. */
  630. public function addWebsiteNamesToResult()
  631. {
  632. $productWebsites = array();
  633. foreach ($this as $product) {
  634. $productWebsites[$product->getId()] = array();
  635. }
  636.  
  637. if (!empty($productWebsites)) {
  638. $select = $this->getConnection()->select()
  639. ->from(array('product_website' => $this->_productWebsiteTable))
  640. ->join(
  641. array('website' => $this->getResource()->getTable('core/website')),
  642. 'website.website_id = product_website.website_id',
  643. array('name'))
  644. ->where('product_website.product_id IN (?)', array_keys($productWebsites))
  645. ->where('website.website_id > ?', 0);
  646.  
  647. $data = $this->getConnection()->fetchAll($select);
  648. foreach ($data as $row) {
  649. $productWebsites[$row['product_id']][] = $row['website_id'];
  650. }
  651. }
  652.  
  653. foreach ($this as $product) {
  654. if (isset($productWebsites[$product->getId()])) {
  655. $product->setData('websites', $productWebsites[$product->getId()]);
  656. }
  657. }
  658. return $this;
  659. }
  660.  
  661. /**
  662. * Add store availability filter. Include availability product
  663. * for store website
  664. *
  665. * @param mixed $store
  666. * @return Mage_Catalog_Model_Resource_Product_Collection
  667. */
  668. public function addStoreFilter($store = null)
  669. {
  670. if ($store === null) {
  671. $store = $this->getStoreId();
  672. }
  673. $store = Mage::app()->getStore($store);
  674.  
  675. if (!$store->isAdmin()) {
  676. $this->_productLimitationFilters['store_id'] = $store->getId();
  677. $this->_applyProductLimitations();
  678. }
  679.  
  680. return $this;
  681. }
  682.  
  683. /**
  684. * Add website filter to collection
  685. *
  686. * @param unknown_type $websites
  687. * @return Mage_Catalog_Model_Resource_Product_Collection
  688. */
  689. public function addWebsiteFilter($websites = null)
  690. {
  691. if (!is_array($websites)) {
  692. $websites = array(Mage::app()->getWebsite($websites)->getId());
  693. }
  694.  
  695. $this->_productLimitationFilters['website_ids'] = $websites;
  696. $this->_applyProductLimitations();
  697.  
  698. return $this;
  699. }
  700.  
  701. /**
  702. * Get filters applied to collection
  703. *
  704. * @return array
  705. */
  706. public function getLimitationFilters()
  707. {
  708. return $this->_productLimitationFilters;
  709. }
  710.  
  711. /**
  712. * Specify category filter for product collection
  713. *
  714. * @param Mage_Catalog_Model_Category $category
  715. * @return Mage_Catalog_Model_Resource_Product_Collection
  716. */
  717. public function addCategoryFilter(Mage_Catalog_Model_Category $category)
  718. {
  719. $this->_productLimitationFilters['category_id'] = $category->getId();
  720. if ($category->getIsAnchor()) {
  721. unset($this->_productLimitationFilters['category_is_anchor']);
  722. } else {
  723. $this->_productLimitationFilters['category_is_anchor'] = 1;
  724. }
  725.  
  726. if ($this->getStoreId() == Mage_Catalog_Model_Abstract::DEFAULT_STORE_ID) {
  727. $this->_applyZeroStoreProductLimitations();
  728. } else {
  729. $this->_applyProductLimitations();
  730. }
  731.  
  732. return $this;
  733. }
  734.  
  735. /**
  736. * Join minimal price attribute to result
  737. *
  738. * @return Mage_Catalog_Model_Resource_Product_Collection
  739. */
  740. public function joinMinimalPrice()
  741. {
  742. $this->addAttributeToSelect('price')
  743. ->addAttributeToSelect('minimal_price');
  744. return $this;
  745. }
  746.  
  747. /**
  748. * Retrieve max value by attribute
  749. *
  750. * @param string $attribute
  751. * @return mixed
  752. */
  753. public function getMaxAttributeValue($attribute)
  754. {
  755. $select = clone $this->getSelect();
  756. $attribute = $this->getEntity()->getAttribute($attribute);
  757. $attributeCode = $attribute->getAttributeCode();
  758. $tableAlias = $attributeCode . '_max_value';
  759. $fieldAlias = 'max_' . $attributeCode;
  760. $condition = 'e.entity_id = ' . $tableAlias . '.entity_id
  761. AND '.$this->_getConditionSql($tableAlias . '.attribute_id', $attribute->getId());
  762.  
  763. $select->join(
  764. array($tableAlias => $attribute->getBackend()->getTable()),
  765. $condition,
  766. array($fieldAlias => new Zend_Db_Expr('MAX('.$tableAlias.'.value)'))
  767. )
  768. ->group('e.entity_type_id');
  769.  
  770. $data = $this->getConnection()->fetchRow($select);
  771. if (isset($data[$fieldAlias])) {
  772. return $data[$fieldAlias];
  773. }
  774.  
  775. return null;
  776. }
  777.  
  778. /**
  779. * Retrieve ranging product count for arrtibute range
  780. *
  781. * @param string $attribute
  782. * @param int $range
  783. * @return array
  784. */
  785. public function getAttributeValueCountByRange($attribute, $range)
  786. {
  787. $select = clone $this->getSelect();
  788. $attribute = $this->getEntity()->getAttribute($attribute);
  789. $attributeCode = $attribute->getAttributeCode();
  790. $tableAlias = $attributeCode . '_range_count_value';
  791.  
  792. $condition = 'e.entity_id = ' . $tableAlias . '.entity_id
  793. AND ' . $this->_getConditionSql($tableAlias . '.attribute_id', $attribute->getId());
  794.  
  795. $select->reset(Zend_Db_Select::GROUP);
  796. $select->join(
  797. array($tableAlias => $attribute->getBackend()->getTable()),
  798. $condition,
  799. array(
  800. 'count_' . $attributeCode => new Zend_Db_Expr('COUNT(DISTINCT e.entity_id)'),
  801. 'range_' . $attributeCode => new Zend_Db_Expr(
  802. 'CEIL((' . $tableAlias . '.value+0.01)/' . $range . ')')
  803. )
  804. )
  805. ->group('range_' . $attributeCode);
  806.  
  807. $data = $this->getConnection()->fetchAll($select);
  808. $res = array();
  809.  
  810. foreach ($data as $row) {
  811. $res[$row['range_' . $attributeCode]] = $row['count_' . $attributeCode];
  812. }
  813. return $res;
  814. }
  815.  
  816. /**
  817. * Retrieve product count by some value of attribute
  818. *
  819. * @param string $attribute
  820. * @return array($value=>$count)
  821. */
  822. public function getAttributeValueCount($attribute)
  823. {
  824. $select = clone $this->getSelect();
  825. $attribute = $this->getEntity()->getAttribute($attribute);
  826. $attributeCode = $attribute->getAttributeCode();
  827. $tableAlias = $attributeCode . '_value_count';
  828.  
  829. $select->reset(Zend_Db_Select::GROUP);
  830. $condition = 'e.entity_id=' . $tableAlias . '.entity_id
  831. AND '.$this->_getConditionSql($tableAlias . '.attribute_id', $attribute->getId());
  832.  
  833. $select->join(
  834. array($tableAlias => $attribute->getBackend()->getTable()),
  835. $condition,
  836. array(
  837. 'count_' . $attributeCode => new Zend_Db_Expr('COUNT(DISTINCT e.entity_id)'),
  838. 'value_' . $attributeCode => new Zend_Db_Expr($tableAlias . '.value')
  839. )
  840. )
  841. ->group('value_' . $attributeCode);
  842.  
  843. $data = $this->getConnection()->fetchAll($select);
  844. $res = array();
  845.  
  846. foreach ($data as $row) {
  847. $res[$row['value_' . $attributeCode]] = $row['count_' . $attributeCode];
  848. }
  849. return $res;
  850. }
  851.  
  852. /**
  853. * Return all attribute values as array in form:
  854. * array(
  855. * [entity_id_1] => array(
  856. * [store_id_1] => store_value_1,
  857. * [store_id_2] => store_value_2,
  858. * ...
  859. * [store_id_n] => store_value_n
  860. * ),
  861. * ...
  862. * )
  863. *
  864. * @param string $attribute attribute code
  865. * @return array
  866. */
  867. public function getAllAttributeValues($attribute)
  868. {
  869. /** @var $select Varien_Db_Select */
  870. $select = clone $this->getSelect();
  871. $attribute = $this->getEntity()->getAttribute($attribute);
  872.  
  873. $select->reset()
  874. ->from($attribute->getBackend()->getTable(), array('entity_id', 'store_id', 'value'))
  875. ->where('attribute_id = ?', (int)$attribute->getId());
  876.  
  877. $data = $this->getConnection()->fetchAll($select);
  878. $res = array();
  879.  
  880. foreach ($data as $row) {
  881. $res[$row['entity_id']][$row['store_id']] = $row['value'];
  882. }
  883.  
  884. return $res;
  885. }
  886.  
  887. /**
  888. * Get SQL for get record count without left JOINs
  889. *
  890. * @return Varien_Db_Select
  891. */
  892. public function getSelectCountSql()
  893. {
  894. return $this->_getSelectCountSql();
  895. }
  896.  
  897. /**
  898. * Get SQL for get record count
  899. *
  900. * @param bool $resetLeftJoins
  901. * @return Varien_Db_Select
  902. */
  903. protected function _getSelectCountSql($select = null, $resetLeftJoins = true)
  904. {
  905. $this->_renderFilters();
  906. $countSelect = (is_null($select)) ?
  907. $this->_getClearSelect() :
  908. $this->_buildClearSelect($select);
  909. $countSelect->columns('COUNT(DISTINCT e.entity_id)');
  910. if ($resetLeftJoins) {
  911. $countSelect->resetJoinLeft();
  912. }
  913. return $countSelect;
  914. }
  915.  
  916. /**
  917. * Prepare statistics data
  918. *
  919. * @return Mage_Catalog_Model_Resource_Product_Collection
  920. */
  921. protected function _prepareStatisticsData()
  922. {
  923. $select = clone $this->getSelect();
  924. $priceExpression = $this->getPriceExpression($select) . ' ' . $this->getAdditionalPriceExpression($select);
  925. $sqlEndPart = ') * ' . $this->getCurrencyRate() . ', 2)';
  926. $select = $this->_getSelectCountSql($select, false);
  927. $select->columns(array(
  928. 'max' => 'ROUND(MAX(' . $priceExpression . $sqlEndPart,
  929. 'min' => 'ROUND(MIN(' . $priceExpression . $sqlEndPart,
  930. 'std' => $this->getConnection()->getStandardDeviationSql('ROUND((' . $priceExpression . $sqlEndPart)
  931. ));
  932. $select->where($this->getPriceExpression($select) . ' IS NOT NULL');
  933. $row = $this->getConnection()->fetchRow($select, $this->_bindParams, Zend_Db::FETCH_NUM);
  934. $this->_pricesCount = (int)$row[0];
  935. $this->_maxPrice = (float)$row[1];
  936. $this->_minPrice = (float)$row[2];
  937. $this->_priceStandardDeviation = (float)$row[3];
  938.  
  939. return $this;
  940. }
  941.  
  942. /**
  943. * Retreive clear select
  944. *
  945. * @return Varien_Db_Select
  946. */
  947. protected function _getClearSelect()
  948. {
  949. return $this->_buildClearSelect();
  950. }
  951.  
  952. /**
  953. * Build clear select
  954. *
  955. * @param Varien_Db_Select $select
  956. * @return Varien_Db_Select
  957. */
  958. protected function _buildClearSelect($select = null)
  959. {
  960. if (is_null($select)) {
  961. $select = clone $this->getSelect();
  962. }
  963. $select->reset(Zend_Db_Select::ORDER);
  964. $select->reset(Zend_Db_Select::LIMIT_COUNT);
  965. $select->reset(Zend_Db_Select::LIMIT_OFFSET);
  966. $select->reset(Zend_Db_Select::COLUMNS);
  967.  
  968. return $select;
  969. }
  970.  
  971. /**
  972. * Retrive all ids for collection
  973. *
  974. * @param unknown_type $limit
  975. * @param unknown_type $offset
  976. * @return array
  977. */
  978. public function getAllIds($limit = null, $offset = null)
  979. {
  980. $idsSelect = $this->_getClearSelect();
  981. $idsSelect->columns('e.' . $this->getEntity()->getIdFieldName());
  982. $idsSelect->limit($limit, $offset);
  983. $idsSelect->resetJoinLeft();
  984.  
  985. return $this->getConnection()->fetchCol($idsSelect, $this->_bindParams);
  986. }
  987.  
  988. /**
  989. * Retreive product count select for categories
  990. *
  991. * @return Varien_Db_Select
  992. */
  993. public function getProductCountSelect()
  994. {
  995. if ($this->_productCountSelect === null) {
  996. $this->_productCountSelect = clone $this->getSelect();
  997. $this->_productCountSelect->reset(Zend_Db_Select::COLUMNS)
  998. ->reset(Zend_Db_Select::GROUP)
  999. ->reset(Zend_Db_Select::ORDER)
  1000. ->distinct(false)
  1001. ->join(array('count_table' => $this->getTable('catalog/category_product_index')),
  1002. 'count_table.product_id = e.entity_id',
  1003. array(
  1004. 'count_table.category_id',
  1005. 'product_count' => new Zend_Db_Expr('COUNT(DISTINCT count_table.product_id)')
  1006. )
  1007. )
  1008. ->where('count_table.store_id = ?', $this->getStoreId())
  1009. ->group('count_table.category_id');
  1010. }
  1011.  
  1012. return $this->_productCountSelect;
  1013. }
  1014.  
  1015. /**
  1016. * Destruct product count select
  1017. *
  1018. * @return Mage_Catalog_Model_Resource_Product_Collection
  1019. */
  1020. public function unsProductCountSelect()
  1021. {
  1022. $this->_productCountSelect = null;
  1023. return $this;
  1024. }
  1025.  
  1026. /**
  1027. * Adding product count to categories collection
  1028. *
  1029. * @param Mage_Eav_Model_Entity_Collection_Abstract $categoryCollection
  1030. * @return Mage_Catalog_Model_Resource_Product_Collection
  1031. */
  1032. public function addCountToCategories($categoryCollection)
  1033. {
  1034. $isAnchor = array();
  1035. $isNotAnchor = array();
  1036. foreach ($categoryCollection as $category) {
  1037. if ($category->getIsAnchor()) {
  1038. $isAnchor[] = $category->getId();
  1039. } else {
  1040. $isNotAnchor[] = $category->getId();
  1041. }
  1042. }
  1043. $productCounts = array();
  1044. if ($isAnchor || $isNotAnchor) {
  1045. $select = $this->getProductCountSelect();
  1046.  
  1047. Mage::dispatchEvent(
  1048. 'catalog_product_collection_before_add_count_to_categories',
  1049. array('collection' => $this)
  1050. );
  1051.  
  1052. if ($isAnchor) {
  1053. $anchorStmt = clone $select;
  1054. $anchorStmt->limit(); //reset limits
  1055. $anchorStmt->where('count_table.category_id IN (?)', $isAnchor);
  1056. $productCounts += $this->getConnection()->fetchPairs($anchorStmt);
  1057. $anchorStmt = null;
  1058. }
  1059. if ($isNotAnchor) {
  1060. $notAnchorStmt = clone $select;
  1061. $notAnchorStmt->limit(); //reset limits
  1062. $notAnchorStmt->where('count_table.category_id IN (?)', $isNotAnchor);
  1063. $notAnchorStmt->where('count_table.is_parent = 1');
  1064. $productCounts += $this->getConnection()->fetchPairs($notAnchorStmt);
  1065. $notAnchorStmt = null;
  1066. }
  1067. $select = null;
  1068. $this->unsProductCountSelect();
  1069. }
  1070.  
  1071. foreach ($categoryCollection as $category) {
  1072. $_count = 0;
  1073. if (isset($productCounts[$category->getId()])) {
  1074. $_count = $productCounts[$category->getId()];
  1075. }
  1076. $category->setProductCount($_count);
  1077. }
  1078.  
  1079. return $this;
  1080. }
  1081.  
  1082. /**
  1083. * Retrieve unique attribute set ids in collection
  1084. *
  1085. * @return array
  1086. */
  1087. public function getSetIds()
  1088. {
  1089. $select = clone $this->getSelect();
  1090. /** @var $select Varien_Db_Select */
  1091. $select->reset(Zend_Db_Select::COLUMNS);
  1092. $select->distinct(true);
  1093. $select->columns('attribute_set_id');
  1094. return $this->getConnection()->fetchCol($select);
  1095. }
  1096.  
  1097. /**
  1098. * Return array of unique product type ids in collection
  1099. *
  1100. * @return array
  1101. */
  1102. public function getProductTypeIds()
  1103. {
  1104. $select = clone $this->getSelect();
  1105. /** @var $select Varien_Db_Select */
  1106. $select->reset(Zend_Db_Select::COLUMNS);
  1107. $select->distinct(true);
  1108. $select->columns('type_id');
  1109. return $this->getConnection()->fetchCol($select);
  1110. }
  1111.  
  1112. /**
  1113. * Joins url rewrite rules to collection
  1114. *
  1115. * @deprecated after 1.7.0.2. Method is not used anywhere in the code.
  1116. * @return Mage_Catalog_Model_Resource_Product_Collection
  1117. */
  1118. public function joinUrlRewrite()
  1119. {
  1120. $this->joinTable(
  1121. 'core/url_rewrite',
  1122. 'entity_id=entity_id',
  1123. array('request_path'),
  1124. '{{table}}.type = ' . Mage_Core_Model_Url_Rewrite::TYPE_PRODUCT,
  1125. 'left'
  1126. );
  1127.  
  1128. return $this;
  1129. }
  1130.  
  1131. /**
  1132. * Add URL rewrites data to product
  1133. * If collection loadded - run processing else set flag
  1134. *
  1135. * @param int|string $categoryId
  1136. * @return Mage_Catalog_Model_Resource_Product_Collection
  1137. */
  1138. public function addUrlRewrite($categoryId = '')
  1139. {
  1140. $this->_addUrlRewrite = true;
  1141. if (Mage::getStoreConfig(Mage_Catalog_Helper_Product::XML_PATH_PRODUCT_URL_USE_CATEGORY, $this->getStoreId())) {
  1142. $this->_urlRewriteCategory = $categoryId;
  1143. } else {
  1144. $this->_urlRewriteCategory = 0;
  1145. }
  1146.  
  1147. if ($this->isLoaded()) {
  1148. $this->_addUrlRewrite();
  1149. }
  1150.  
  1151. return $this;
  1152. }
  1153.  
  1154. /**
  1155. * Add URL rewrites to collection
  1156. *
  1157. */
  1158. protected function _addUrlRewrite()
  1159. {
  1160. $urlRewrites = null;
  1161. if ($this->_cacheConf) {
  1162. if (!($urlRewrites = Mage::app()->loadCache($this->_cacheConf['prefix'] . 'urlrewrite'))) {
  1163. $urlRewrites = null;
  1164. } else {
  1165. $urlRewrites = unserialize($urlRewrites);
  1166. }
  1167. }
  1168.  
  1169. if (!$urlRewrites) {
  1170. $productIds = array();
  1171. foreach($this->getItems() as $item) {
  1172. $productIds[] = $item->getEntityId();
  1173. }
  1174. if (!count($productIds)) {
  1175. return;
  1176. }
  1177.  
  1178. $select = $this->_factory->getProductUrlRewriteHelper()
  1179. ->getTableSelect($productIds, $this->_urlRewriteCategory, Mage::app()->getStore()->getId());
  1180.  
  1181. $urlRewrites = array();
  1182. foreach ($this->getConnection()->fetchAll($select) as $row) {
  1183. if (!isset($urlRewrites[$row['product_id']])) {
  1184. $urlRewrites[$row['product_id']] = $row['request_path'];
  1185. }
  1186. }
  1187.  
  1188. if ($this->_cacheConf) {
  1189. Mage::app()->saveCache(
  1190. serialize($urlRewrites),
  1191. $this->_cacheConf['prefix'] . 'urlrewrite',
  1192. array_merge($this->_cacheConf['tags'], array(Mage_Catalog_Model_Product_Url::CACHE_TAG)),
  1193. $this->_cacheLifetime
  1194. );
  1195. }
  1196. }
  1197.  
  1198. foreach($this->getItems() as $item) {
  1199. if (empty($this->_urlRewriteCategory)) {
  1200. $item->setDoNotUseCategoryId(true);
  1201. }
  1202. if (isset($urlRewrites[$item->getEntityId()])) {
  1203. $item->setData('request_path', $urlRewrites[$item->getEntityId()]);
  1204. } else {
  1205. $item->setData('request_path', false);
  1206. }
  1207. }
  1208. }
  1209.  
  1210. /**
  1211. * Add minimal price data to result
  1212. *
  1213. * @return Mage_Catalog_Model_Resource_Product_Collection
  1214. */
  1215. public function addMinimalPrice()
  1216. {
  1217. return $this->addPriceData();
  1218. }
  1219.  
  1220. /**
  1221. * Add minimal price to product collection
  1222. *
  1223. * @deprecated sinse 1.3.2.2
  1224. * @see Mage_Catalog_Model_Resource_Product_Collection::addPriceData
  1225. *
  1226. * @return Mage_Catalog_Model_Resource_Product_Collection
  1227. */
  1228. protected function _addMinimalPrice()
  1229. {
  1230. return $this;
  1231. }
  1232.  
  1233. /**
  1234. * Add price data for calculate final price
  1235. *
  1236. * @return Mage_Catalog_Model_Resource_Product_Collection
  1237. */
  1238. public function addFinalPrice()
  1239. {
  1240. return $this->addPriceData();
  1241. }
  1242.  
  1243. /**
  1244. * Join prices from price rules to products collection
  1245. *
  1246. * @return Mage_Catalog_Model_Resource_Product_Collection
  1247. */
  1248. protected function _joinPriceRules()
  1249. {
  1250. if ($this->isEnabledFlat()) {
  1251. $customerGroup = Mage::getSingleton('customer/session')->getCustomerGroupId();
  1252. $priceColumn = 'e.display_price_group_' . $customerGroup;
  1253. $this->getSelect()->columns(array('_rule_price' => $priceColumn));
  1254.  
  1255. return $this;
  1256. }
  1257. if (!Mage::helper('catalog')->isModuleEnabled('Mage_CatalogRule')) {
  1258. return $this;
  1259. }
  1260. $wId = Mage::app()->getWebsite()->getId();
  1261. $gId = Mage::getSingleton('customer/session')->getCustomerGroupId();
  1262.  
  1263. $storeDate = Mage::app()->getLocale()->storeTimeStamp($this->getStoreId());
  1264. $conditions = 'price_rule.product_id = e.entity_id AND ';
  1265. $conditions .= "price_rule.rule_date = '".$this->getResource()->formatDate($storeDate, false)."' AND ";
  1266. $conditions .= $this->getConnection()->quoteInto('price_rule.website_id = ? AND', $wId);
  1267. $conditions .= $this->getConnection()->quoteInto('price_rule.customer_group_id = ?', $gId);
  1268.  
  1269. $this->getSelect()->joinLeft(
  1270. array('price_rule' => $this->getTable('catalogrule/rule_product_price')),
  1271. $conditions,
  1272. array('rule_price' => 'rule_price')
  1273. );
  1274. return $this;
  1275. }
  1276.  
  1277. /**
  1278. * Add final price to the product
  1279. *
  1280. * @return Mage_Catalog_Model_Resource_Product_Collection
  1281. */
  1282. protected function _addFinalPrice()
  1283. {
  1284. foreach ($this->_items as $product) {
  1285. $basePrice = $product->getPrice();
  1286. $specialPrice = $product->getSpecialPrice();
  1287. $specialPriceFrom = $product->getSpecialFromDate();
  1288. $specialPriceTo = $product->getSpecialToDate();
  1289. if ($this->isEnabledFlat()) {
  1290. $rulePrice = null;
  1291. if ($product->getData('_rule_price') != $basePrice) {
  1292. $rulePrice = $product->getData('_rule_price');
  1293. }
  1294. } else {
  1295. $rulePrice = $product->getData('_rule_price');
  1296. }
  1297.  
  1298. $finalPrice = $product->getPriceModel()->calculatePrice(
  1299. $basePrice,
  1300. $specialPrice,
  1301. $specialPriceFrom,
  1302. $specialPriceTo,
  1303. $rulePrice,
  1304. null,
  1305. null,
  1306. $product->getId()
  1307. );
  1308.  
  1309. $product->setCalculatedFinalPrice($finalPrice);
  1310. }
  1311.  
  1312. return $this;
  1313. }
  1314.  
  1315. /**
  1316. * Retreive all ids
  1317. *
  1318. * @param boolean $resetCache
  1319. * @return array
  1320. */
  1321. public function getAllIdsCache($resetCache = false)
  1322. {
  1323. $ids = null;
  1324. if (!$resetCache) {
  1325. $ids = $this->_allIdsCache;
  1326. }
  1327.  
  1328. if (is_null($ids)) {
  1329. $ids = $this->getAllIds();
  1330. $this->setAllIdsCache($ids);
  1331. }
  1332.  
  1333. return $ids;
  1334. }
  1335.  
  1336. /**
  1337. * Set all ids
  1338. *
  1339. * @param array $value
  1340. * @return Mage_Catalog_Model_Resource_Product_Collection
  1341. */
  1342. public function setAllIdsCache($value)
  1343. {
  1344. $this->_allIdsCache = $value;
  1345. return $this;
  1346. }
  1347.  
  1348. /**
  1349. * Add Price Data to result
  1350. *
  1351. * @param int $customerGroupId
  1352. * @param int $websiteId
  1353. * @return Mage_Catalog_Model_Resource_Product_Collection
  1354. */
  1355. public function addPriceData($customerGroupId = null, $websiteId = null)
  1356. {
  1357. $this->_productLimitationFilters['use_price_index'] = true;
  1358.  
  1359. if (!isset($this->_productLimitationFilters['customer_group_id']) && is_null($customerGroupId)) {
  1360. $customerGroupId = Mage::getSingleton('customer/session')->getCustomerGroupId();
  1361. }
  1362. if (!isset($this->_productLimitationFilters['website_id']) && is_null($websiteId)) {
  1363. $websiteId = Mage::app()->getStore($this->getStoreId())->getWebsiteId();
  1364. }
  1365.  
  1366. if (!is_null($customerGroupId)) {
  1367. $this->_productLimitationFilters['customer_group_id'] = $customerGroupId;
  1368. }
  1369. if (!is_null($websiteId)) {
  1370. $this->_productLimitationFilters['website_id'] = $websiteId;
  1371. }
  1372.  
  1373. $this->_applyProductLimitations();
  1374.  
  1375. return $this;
  1376. }
  1377.  
  1378. /**
  1379. * Add attribute to filter
  1380. *
  1381. * @param Mage_Eav_Model_Entity_Attribute_Abstract|string $attribute
  1382. * @param array $condition
  1383. * @param string $joinType
  1384. * @return Mage_Catalog_Model_Resource_Product_Collection
  1385. */
  1386. public function addAttributeToFilter($attribute, $condition = null, $joinType = 'inner')
  1387. {
  1388. if ($this->isEnabledFlat()) {
  1389. if ($attribute instanceof Mage_Eav_Model_Entity_Attribute_Abstract) {
  1390. $attribute = $attribute->getAttributeCode();
  1391. }
  1392.  
  1393. if (is_array($attribute)) {
  1394. $sqlArr = array();
  1395. foreach ($attribute as $condition) {
  1396. $sqlArr[] = $this->_getAttributeConditionSql($condition['attribute'], $condition, $joinType);
  1397. }
  1398. $conditionSql = '('.join(') OR (', $sqlArr).')';
  1399. $this->getSelect()->where($conditionSql);
  1400. return $this;
  1401. }
  1402.  
  1403. if (!isset($this->_selectAttributes[$attribute])) {
  1404. $this->addAttributeToSelect($attribute);
  1405. }
  1406.  
  1407. if (isset($this->_selectAttributes[$attribute])) {
  1408. $this->getSelect()->where($this->_getConditionSql('e.' . $attribute, $condition));
  1409. }
  1410.  
  1411. return $this;
  1412. }
  1413.  
  1414. $this->_allIdsCache = null;
  1415.  
  1416. if (is_string($attribute) && $attribute == 'is_saleable') {
  1417. $columns = $this->getSelect()->getPart(Zend_Db_Select::COLUMNS);
  1418. foreach ($columns as $columnEntry) {
  1419. list($correlationName, $column, $alias) = $columnEntry;
  1420. if ($alias == 'is_saleable') {
  1421. if ($column instanceof Zend_Db_Expr) {
  1422. $field = $column;
  1423. } else {
  1424. $adapter = $this->getSelect()->getAdapter();
  1425. if (empty($correlationName)) {
  1426. $field = $adapter->quoteColumnAs($column, $alias, true);
  1427. } else {
  1428. $field = $adapter->quoteColumnAs(array($correlationName, $column), $alias, true);
  1429. }
  1430. }
  1431. $this->getSelect()->where("{$field} = ?", $condition);
  1432. break;
  1433. }
  1434. }
  1435.  
  1436. return $this;
  1437. } else {
  1438. return parent::addAttributeToFilter($attribute, $condition, $joinType);
  1439. }
  1440. }
  1441.  
  1442. /**
  1443. * Add requere tax percent flag for product collection
  1444. *
  1445. * @return Mage_Catalog_Model_Resource_Product_Collection
  1446. */
  1447. public function addTaxPercents()
  1448. {
  1449. $this->_addTaxPercents = true;
  1450. return $this;
  1451. }
  1452.  
  1453. /**
  1454. * Get require tax percent flag value
  1455. *
  1456. * @return bool
  1457. */
  1458. public function requireTaxPercent()
  1459. {
  1460. return $this->_addTaxPercents;
  1461. }
  1462.  
  1463. /**
  1464. * Enter description here ...
  1465. *
  1466. * @deprecated from 1.3.0
  1467. *
  1468. */
  1469. protected function _addTaxPercents()
  1470. {
  1471. $classToRate = array();
  1472. $request = Mage::getSingleton('tax/calculation')->getRateRequest();
  1473. foreach ($this as &$item) {
  1474. if (null === $item->getTaxClassId()) {
  1475. $item->setTaxClassId($item->getMinimalTaxClassId());
  1476. }
  1477. if (!isset($classToRate[$item->getTaxClassId()])) {
  1478. $request->setProductClassId($item->getTaxClassId());
  1479. $classToRate[$item->getTaxClassId()] = Mage::getSingleton('tax/calculation')->getRate($request);
  1480. }
  1481. $item->setTaxPercent($classToRate[$item->getTaxClassId()]);
  1482. }
  1483. }
  1484.  
  1485. /**
  1486. * Adding product custom options to result collection
  1487. *
  1488. * @return Mage_Catalog_Model_Resource_Product_Collection
  1489. */
  1490. public function addOptionsToResult()
  1491. {
  1492. $productIds = array();
  1493. foreach ($this as $product) {
  1494. $productIds[] = $product->getId();
  1495. }
  1496. if (!empty($productIds)) {
  1497. $options = Mage::getModel('catalog/product_option')
  1498. ->getCollection()
  1499. ->addTitleToResult(Mage::app()->getStore()->getId())
  1500. ->addPriceToResult(Mage::app()->getStore()->getId())
  1501. ->addProductToFilter($productIds)
  1502. ->addValuesToResult();
  1503.  
  1504. foreach ($options as $option) {
  1505. if($this->getItemById($option->getProductId())) {
  1506. $this->getItemById($option->getProductId())->addOption($option);
  1507. }
  1508. }
  1509. }
  1510.  
  1511. return $this;
  1512. }
  1513.  
  1514. /**
  1515. * Filter products with required options
  1516. *
  1517. * @return Mage_Catalog_Model_Resource_Product_Collection
  1518. */
  1519. public function addFilterByRequiredOptions()
  1520. {
  1521. $this->addAttributeToFilter('required_options', array(array('neq' => '1'), array('null' => true)), 'left');
  1522. return $this;
  1523. }
  1524.  
  1525. /**
  1526. * Set product visibility filter for enabled products
  1527. *
  1528. * @param array $visibility
  1529. * @return Mage_Catalog_Model_Resource_Product_Collection
  1530. */
  1531. public function setVisibility($visibility)
  1532. {
  1533. $this->_productLimitationFilters['visibility'] = $visibility;
  1534. $this->_applyProductLimitations();
  1535.  
  1536. return $this;
  1537. }
  1538.  
  1539. /**
  1540. * Add attribute to sort order
  1541. *
  1542. * @param string $attribute
  1543. * @param string $dir
  1544. * @return Mage_Catalog_Model_Resource_Product_Collection
  1545. */
  1546. public function addAttributeToSort($attribute, $dir = self::SORT_ORDER_ASC)
  1547. {
  1548. if ($attribute == 'position') {
  1549. if (isset($this->_joinFields[$attribute])) {
  1550. $this->getSelect()->order($this->_getAttributeFieldName($attribute) . ' ' . $dir);
  1551. return $this;
  1552. }
  1553. if ($this->isEnabledFlat()) {
  1554. $this->getSelect()->order("cat_index_position {$dir}");
  1555. }
  1556. // optimize if using cat index
  1557. $filters = $this->_productLimitationFilters;
  1558. if (isset($filters['category_id']) || isset($filters['visibility'])) {
  1559. $this->getSelect()->order('cat_index.position ' . $dir);
  1560. } else {
  1561. $this->getSelect()->order('e.entity_id ' . $dir);
  1562. }
  1563.  
  1564. return $this;
  1565. } elseif($attribute == 'is_saleable'){
  1566. $this->getSelect()->order("is_saleable " . $dir);
  1567. return $this;
  1568. }
  1569.  
  1570. $storeId = $this->getStoreId();
  1571. if ($attribute == 'price' && $storeId != 0) {
  1572. $this->addPriceData();
  1573. $this->getSelect()->order("price_index.min_price {$dir}");
  1574.  
  1575. return $this;
  1576. }
  1577.  
  1578. if ($this->isEnabledFlat()) {
  1579. $column = $this->getEntity()->getAttributeSortColumn($attribute);
  1580.  
  1581. if ($column) {
  1582. $this->getSelect()->order("e.{$column} {$dir}");
  1583. }
  1584. else if (isset($this->_joinFields[$attribute])) {
  1585. $this->getSelect()->order($this->_getAttributeFieldName($attribute) . ' ' . $dir);
  1586. }
  1587.  
  1588. return $this;
  1589. } else {
  1590. $attrInstance = $this->getEntity()->getAttribute($attribute);
  1591. if ($attrInstance && $attrInstance->usesSource()) {
  1592. $attrInstance->getSource()
  1593. ->addValueSortToCollection($this, $dir);
  1594. return $this;
  1595. }
  1596. }
  1597.  
  1598. return parent::addAttributeToSort($attribute, $dir);
  1599. }
  1600.  
  1601. /**
  1602. * Prepare limitation filters
  1603. *
  1604. * @return Mage_Catalog_Model_Resource_Product_Collection
  1605. */
  1606. protected function _prepareProductLimitationFilters()
  1607. {
  1608. if (isset($this->_productLimitationFilters['visibility'])
  1609. && !isset($this->_productLimitationFilters['store_id'])
  1610. ) {
  1611. $this->_productLimitationFilters['store_id'] = $this->getStoreId();
  1612. }
  1613. if (isset($this->_productLimitationFilters['category_id'])
  1614. && !isset($this->_productLimitationFilters['store_id'])
  1615. ) {
  1616. $this->_productLimitationFilters['store_id'] = $this->getStoreId();
  1617. }
  1618. if (isset($this->_productLimitationFilters['store_id'])
  1619. && isset($this->_productLimitationFilters['visibility'])
  1620. && !isset($this->_productLimitationFilters['category_id'])
  1621. ) {
  1622. $this->_productLimitationFilters['category_id'] = Mage::app()
  1623. ->getStore($this->_productLimitationFilters['store_id'])
  1624. ->getRootCategoryId();
  1625. }
  1626.  
  1627. return $this;
  1628. }
  1629.  
  1630. /**
  1631. * Join website product limitation
  1632. *
  1633. * @return Mage_Catalog_Model_Resource_Product_Collection
  1634. */
  1635. protected function _productLimitationJoinWebsite()
  1636. {
  1637. $joinWebsite = false;
  1638. $filters = $this->_productLimitationFilters;
  1639. $conditions = array('product_website.product_id = e.entity_id');
  1640.  
  1641. if (isset($filters['website_ids'])) {
  1642. $joinWebsite = true;
  1643. if (count($filters['website_ids']) > 1) {
  1644. $this->getSelect()->distinct(true);
  1645. }
  1646. $conditions[] = $this->getConnection()
  1647. ->quoteInto('product_website.website_id IN(?)', $filters['website_ids']);
  1648. } elseif (isset($filters['store_id'])
  1649. && (!isset($filters['visibility']) && !isset($filters['category_id']))
  1650. && !$this->isEnabledFlat()
  1651. ) {
  1652. $joinWebsite = true;
  1653. $websiteId = Mage::app()->getStore($filters['store_id'])->getWebsiteId();
  1654. $conditions[] = $this->getConnection()
  1655. ->quoteInto('product_website.website_id = ?', $websiteId);
  1656. }
  1657.  
  1658. $fromPart = $this->getSelect()->getPart(Zend_Db_Select::FROM);
  1659. if (isset($fromPart['product_website'])) {
  1660. if (!$joinWebsite) {
  1661. unset($fromPart['product_website']);
  1662. } else {
  1663. $fromPart['product_website']['joinCondition'] = join(' AND ', $conditions);
  1664. }
  1665. $this->getSelect()->setPart(Zend_Db_Select::FROM, $fromPart);
  1666. } elseif ($joinWebsite) {
  1667. $this->getSelect()->join(
  1668. array('product_website' => $this->getTable('catalog/product_website')),
  1669. join(' AND ', $conditions),
  1670. array()
  1671. );
  1672. }
  1673.  
  1674. return $this;
  1675. }
  1676.  
  1677. /**
  1678. * Join additional (alternative) store visibility filter
  1679. *
  1680. * @return Mage_Catalog_Model_Resource_Product_Collection
  1681. */
  1682. protected function _productLimitationJoinStore()
  1683. {
  1684. $filters = $this->_productLimitationFilters;
  1685. if (!isset($filters['store_table'])) {
  1686. return $this;
  1687. }
  1688.  
  1689. $hasColumn = false;
  1690. foreach ($this->getSelect()->getPart(Zend_Db_Select::COLUMNS) as $columnEntry) {
  1691. list(,,$alias) = $columnEntry;
  1692. if ($alias == 'visibility') {
  1693. $hasColumn = true;
  1694. }
  1695. }
  1696. if (!$hasColumn) {
  1697. $this->getSelect()->columns('visibility', 'cat_index');
  1698. }
  1699.  
  1700. $fromPart = $this->getSelect()->getPart(Zend_Db_Select::FROM);
  1701. if (!isset($fromPart['store_index'])) {
  1702. $this->getSelect()->joinLeft(
  1703. array('store_index' => $this->getTable('core/store')),
  1704. 'store_index.store_id = ' . $filters['store_table'] . '.store_id',
  1705. array()
  1706. );
  1707. }
  1708. if (!isset($fromPart['store_group_index'])) {
  1709. $this->getSelect()->joinLeft(
  1710. array('store_group_index' => $this->getTable('core/store_group')),
  1711. 'store_index.group_id = store_group_index.group_id',
  1712. array()
  1713. );
  1714. }
  1715. if (!isset($fromPart['store_cat_index'])) {
  1716. $this->getSelect()->joinLeft(
  1717. array('store_cat_index' => $this->getTable('catalog/category_product_index')),
  1718. join(' AND ', array(
  1719. 'store_cat_index.product_id = e.entity_id',
  1720. 'store_cat_index.store_id = ' . $filters['store_table'] . '.store_id',
  1721. 'store_cat_index.category_id=store_group_index.root_category_id'
  1722. )),
  1723. array('store_visibility' => 'visibility')
  1724. );
  1725. }
  1726. // Avoid column duplication problems
  1727. Mage::getResourceHelper('core')->prepareColumnsList($this->getSelect());
  1728.  
  1729. $whereCond = join(' OR ', array(
  1730. $this->getConnection()->quoteInto('cat_index.visibility IN(?)', $filters['visibility']),
  1731. $this->getConnection()->quoteInto('store_cat_index.visibility IN(?)', $filters['visibility'])
  1732. ));
  1733.  
  1734. $wherePart = $this->getSelect()->getPart(Zend_Db_Select::WHERE);
  1735. $hasCond = false;
  1736. foreach ($wherePart as $cond) {
  1737. if ($cond == '(' . $whereCond . ')') {
  1738. $hasCond = true;
  1739. }
  1740. }
  1741.  
  1742. if (!$hasCond) {
  1743. $this->getSelect()->where($whereCond);
  1744. }
  1745.  
  1746. return $this;
  1747. }
  1748.  
  1749. /**
  1750. * Join Product Price Table
  1751. *
  1752. * @return Mage_Catalog_Model_Resource_Product_Collection
  1753. */
  1754. protected function _productLimitationJoinPrice()
  1755. {
  1756. return $this->_productLimitationPrice();
  1757. }
  1758.  
  1759. /**
  1760. * Join Product Price Table with left-join possibility
  1761. *
  1762. * @see Mage_Catalog_Model_Resource_Product_Collection::_productLimitationJoinPrice()
  1763. * @return Mage_Catalog_Model_Resource_Product_Collection
  1764. */
  1765. protected function _productLimitationPrice($joinLeft = false)
  1766. {
  1767. $filters = $this->_productLimitationFilters;
  1768. if (empty($filters['use_price_index'])) {
  1769. return $this;
  1770. }
  1771.  
  1772. $helper = Mage::getResourceHelper('core');
  1773. $connection = $this->getConnection();
  1774. $select = $this->getSelect();
  1775. $joinCond = join(' AND ', array(
  1776. 'price_index.entity_id = e.entity_id',
  1777. $connection->quoteInto('price_index.website_id = ?', $filters['website_id']),
  1778. $connection->quoteInto('price_index.customer_group_id = ?', $filters['customer_group_id'])
  1779. ));
  1780.  
  1781. $fromPart = $select->getPart(Zend_Db_Select::FROM);
  1782. if (!isset($fromPart['price_index'])) {
  1783. $least = $connection->getLeastSql(array('price_index.min_price', 'price_index.tier_price'));
  1784. $minimalExpr = $connection->getCheckSql('price_index.tier_price IS NOT NULL',
  1785. $least, 'price_index.min_price');
  1786. $colls = array('price', 'tax_class_id', 'final_price',
  1787. 'minimal_price' => $minimalExpr , 'min_price', 'max_price', 'tier_price');
  1788. $tableName = array('price_index' => $this->getTable('catalog/product_index_price'));
  1789. if ($joinLeft) {
  1790. $select->joinLeft($tableName, $joinCond, $colls);
  1791. } else {
  1792. $select->join($tableName, $joinCond, $colls);
  1793. }
  1794. // Set additional field filters
  1795. foreach ($this->_priceDataFieldFilters as $filterData) {
  1796. $select->where(call_user_func_array('sprintf', $filterData));
  1797. }
  1798. } else {
  1799. $fromPart['price_index']['joinCondition'] = $joinCond;
  1800. $select->setPart(Zend_Db_Select::FROM, $fromPart);
  1801. }
  1802. //Clean duplicated fields
  1803. $helper->prepareColumnsList($select);
  1804.  
  1805.  
  1806. return $this;
  1807. }
  1808.  
  1809. /**
  1810. * Apply front-end price limitation filters to the collection
  1811. *
  1812. * @return Mage_Catalog_Model_Resource_Product_Collection
  1813. */
  1814. public function applyFrontendPriceLimitations()
  1815. {
  1816. $this->_productLimitationFilters['use_price_index'] = true;
  1817. if (!isset($this->_productLimitationFilters['customer_group_id'])) {
  1818. $customerGroupId = Mage::getSingleton('customer/session')->getCustomerGroupId();
  1819. $this->_productLimitationFilters['customer_group_id'] = $customerGroupId;
  1820. }
  1821. if (!isset($this->_productLimitationFilters['website_id'])) {
  1822. $websiteId = Mage::app()->getStore($this->getStoreId())->getWebsiteId();
  1823. $this->_productLimitationFilters['website_id'] = $websiteId;
  1824. }
  1825. $this->_applyProductLimitations();
  1826. return $this;
  1827. }
  1828.  
  1829. /**
  1830. * Apply limitation filters to collection
  1831. * Method allows using one time category product index table (or product website table)
  1832. * for different combinations of store_id/category_id/visibility filter states
  1833. * Method supports multiple changes in one collection object for this parameters
  1834. *
  1835. * @return Mage_Catalog_Model_Resource_Product_Collection
  1836. */
  1837. protected function _applyProductLimitations()
  1838. {
  1839. Mage::dispatchEvent('catalog_product_collection_apply_limitations_before', array(
  1840. 'collection' => $this,
  1841. 'category_id' => isset($this->_productLimitationFilters['category_id'])
  1842. ? $this->_productLimitationFilters['category_id']
  1843. : null,
  1844. ));
  1845. $this->_prepareProductLimitationFilters();
  1846. $this->_productLimitationJoinWebsite();
  1847. $this->_productLimitationJoinPrice();
  1848. $filters = $this->_productLimitationFilters;
  1849.  
  1850. if (!isset($filters['category_id']) && !isset($filters['visibility'])) {
  1851. return $this;
  1852. }
  1853.  
  1854. $conditions = array(
  1855. 'cat_index.product_id=e.entity_id',
  1856. $this->getConnection()->quoteInto('cat_index.store_id=?', $filters['store_id'])
  1857. );
  1858. if (isset($filters['visibility']) && !isset($filters['store_table'])) {
  1859. $conditions[] = $this->getConnection()
  1860. ->quoteInto('cat_index.visibility IN(?)', $filters['visibility']);
  1861. }
  1862.  
  1863. if (!$this->getFlag('disable_root_category_filter')) {
  1864. $conditions[] = $this->getConnection()->quoteInto('cat_index.category_id = ?', $filters['category_id']);
  1865. }
  1866.  
  1867. if (isset($filters['category_is_anchor'])) {
  1868. $conditions[] = $this->getConnection()
  1869. ->quoteInto('cat_index.is_parent=?', $filters['category_is_anchor']);
  1870. }
  1871.  
  1872. $joinCond = join(' AND ', $conditions);
  1873. $fromPart = $this->getSelect()->getPart(Zend_Db_Select::FROM);
  1874. if (isset($fromPart['cat_index'])) {
  1875. $fromPart['cat_index']['joinCondition'] = $joinCond;
  1876. $this->getSelect()->setPart(Zend_Db_Select::FROM, $fromPart);
  1877. }
  1878. else {
  1879. $this->getSelect()->join(
  1880. array('cat_index' => $this->getTable('catalog/category_product_index')),
  1881. $joinCond,
  1882. array('cat_index_position' => 'position')
  1883. );
  1884. }
  1885.  
  1886. $this->_productLimitationJoinStore();
  1887.  
  1888. Mage::dispatchEvent('catalog_product_collection_apply_limitations_after', array(
  1889. 'collection' => $this
  1890. ));
  1891.  
  1892. return $this;
  1893. }
  1894.  
  1895. /**
  1896. * Apply limitation filters to collection base on API
  1897. * Method allows using one time category product table
  1898. * for combinations of category_id filter states
  1899. *
  1900. * @return Mage_Catalog_Model_Resource_Product_Collection
  1901. */
  1902. protected function _applyZeroStoreProductLimitations()
  1903. {
  1904. $filters = $this->_productLimitationFilters;
  1905.  
  1906. $conditions = array(
  1907. 'cat_pro.product_id=e.entity_id',
  1908. $this->getConnection()->quoteInto('cat_pro.category_id=?', $filters['category_id'])
  1909. );
  1910. $joinCond = join(' AND ', $conditions);
  1911.  
  1912. $fromPart = $this->getSelect()->getPart(Zend_Db_Select::FROM);
  1913. if (isset($fromPart['cat_pro'])) {
  1914. $fromPart['cat_pro']['joinCondition'] = $joinCond;
  1915. $this->getSelect()->setPart(Zend_Db_Select::FROM, $fromPart);
  1916. }
  1917. else {
  1918. $this->getSelect()->join(
  1919. array('cat_pro' => $this->getTable('catalog/category_product')),
  1920. $joinCond,
  1921. array('cat_index_position' => 'position')
  1922. );
  1923. }
  1924. $this->_joinFields['position'] = array(
  1925. 'table' => 'cat_pro',
  1926. 'field' => 'position',
  1927. );
  1928.  
  1929. return $this;
  1930. }
  1931.  
  1932. /**
  1933. * Add category ids to loaded items
  1934. *
  1935. * @return Mage_Catalog_Model_Resource_Product_Collection
  1936. */
  1937. public function addCategoryIds()
  1938. {
  1939. if ($this->getFlag('category_ids_added')) {
  1940. return $this;
  1941. }
  1942. $ids = array_keys($this->_items);
  1943. if (empty($ids)) {
  1944. return $this;
  1945. }
  1946.  
  1947. $select = $this->getConnection()->select();
  1948.  
  1949. $select->from($this->_productCategoryTable, array('product_id', 'category_id'));
  1950. $select->where('product_id IN (?)', $ids);
  1951.  
  1952. $data = $this->getConnection()->fetchAll($select);
  1953.  
  1954. $categoryIds = array();
  1955. foreach ($data as $info) {
  1956. if (isset($categoryIds[$info['product_id']])) {
  1957. $categoryIds[$info['product_id']][] = $info['category_id'];
  1958. } else {
  1959. $categoryIds[$info['product_id']] = array($info['category_id']);
  1960. }
  1961. }
  1962.  
  1963.  
  1964. foreach ($this->getItems() as $item) {
  1965. $productId = $item->getId();
  1966. if (isset($categoryIds[$productId])) {
  1967. $item->setCategoryIds($categoryIds[$productId]);
  1968. } else {
  1969. $item->setCategoryIds(array());
  1970. }
  1971. }
  1972.  
  1973. $this->setFlag('category_ids_added', true);
  1974. return $this;
  1975. }
  1976.  
  1977. /**
  1978. * Add tier price data to loaded items
  1979. *
  1980. * @return Mage_Catalog_Model_Resource_Product_Collection
  1981. */
  1982. public function addTierPriceData()
  1983. {
  1984. if ($this->getFlag('tier_price_added')) {
  1985. return $this;
  1986. }
  1987.  
  1988. $tierPrices = array();
  1989. $productIds = array();
  1990. foreach ($this->getItems() as $item) {
  1991. $productIds[] = $item->getId();
  1992. $tierPrices[$item->getId()] = array();
  1993. }
  1994. if (!$productIds) {
  1995. return $this;
  1996. }
  1997.  
  1998. /** @var $attribute Mage_Catalog_Model_Resource_Eav_Attribute */
  1999. $attribute = $this->getAttribute('tier_price');
  2000. if ($attribute->isScopeGlobal()) {
  2001. $websiteId = 0;
  2002. } else if ($this->getStoreId()) {
  2003. $websiteId = Mage::app()->getStore($this->getStoreId())->getWebsiteId();
  2004. }
  2005.  
  2006. $adapter = $this->getConnection();
  2007. $columns = array(
  2008. 'price_id' => 'value_id',
  2009. 'website_id' => 'website_id',
  2010. 'all_groups' => 'all_groups',
  2011. 'cust_group' => 'customer_group_id',
  2012. 'price_qty' => 'qty',
  2013. 'price' => 'value',
  2014. 'product_id' => 'entity_id'
  2015. );
  2016. $select = $adapter->select()
  2017. ->from($this->getTable('catalog/product_attribute_tier_price'), $columns)
  2018. ->where('entity_id IN(?)', $productIds)
  2019. ->order(array('entity_id','qty'));
  2020.  
  2021. if ($websiteId == '0') {
  2022. $select->where('website_id = ?', $websiteId);
  2023. } else {
  2024. $select->where('website_id IN(?)', array('0', $websiteId));
  2025. }
  2026.  
  2027. foreach ($adapter->fetchAll($select) as $row) {
  2028. $tierPrices[$row['product_id']][] = array(
  2029. 'website_id' => $row['website_id'],
  2030. 'cust_group' => $row['all_groups'] ? Mage_Customer_Model_Group::CUST_GROUP_ALL : $row['cust_group'],
  2031. 'price_qty' => $row['price_qty'],
  2032. 'price' => $row['price'],
  2033. 'website_price' => $row['price'],
  2034.  
  2035. );
  2036. }
  2037.  
  2038. /* @var $backend Mage_Catalog_Model_Product_Attribute_Backend_Tierprice */
  2039. $backend = $attribute->getBackend();
  2040.  
  2041. foreach ($this->getItems() as $item) {
  2042. $data = $tierPrices[$item->getId()];
  2043. if (!empty($data) && $websiteId) {
  2044. $data = $backend->preparePriceData($data, $item->getTypeId(), $websiteId);
  2045. }
  2046. $item->setData('tier_price', $data);
  2047. }
  2048.  
  2049. $this->setFlag('tier_price_added', true);
  2050. return $this;
  2051. }
  2052.  
  2053. /**
  2054. * Add field comparison expression
  2055. *
  2056. * @param string $comparisonFormat - expression for sprintf()
  2057. * @param array $fields - list of fields
  2058. * @return Mage_Catalog_Model_Resource_Product_Collection
  2059. * @throws Exception
  2060. */
  2061. public function addPriceDataFieldFilter($comparisonFormat, $fields)
  2062. {
  2063. if (!preg_match('/^%s( (<|>|=|<=|>=|<>) %s)*$/', $comparisonFormat)) {
  2064. throw new Exception('Invalid comparison format.');
  2065. }
  2066.  
  2067. if (!is_array($fields)) {
  2068. $fields = array($fields);
  2069. }
  2070. foreach ($fields as $key => $field) {
  2071. $fields[$key] = $this->_getMappedField($field);
  2072. }
  2073.  
  2074. $this->_priceDataFieldFilters[] = array_merge(array($comparisonFormat), $fields);
  2075. return $this;
  2076. }
  2077.  
  2078. /**
  2079. * Clear collection
  2080. *
  2081. * @return Mage_Catalog_Model_Resource_Product_Collection
  2082. */
  2083. public function clear()
  2084. {
  2085. foreach ($this->_items as $i => $item) {
  2086. if ($item->hasStockItem()) {
  2087. $item->unsStockItem();
  2088. }
  2089. $item = $this->_items[$i] = null;
  2090. }
  2091.  
  2092. foreach ($this->_itemsById as $i => $item) {
  2093. $item = $this->_itemsById[$i] = null;
  2094. }
  2095.  
  2096. unset($this->_items, $this->_data, $this->_itemsById);
  2097. $this->_data = array();
  2098. $this->_itemsById = array();
  2099. return parent::clear();
  2100. }
  2101.  
  2102. /**
  2103. * Set Order field
  2104. *
  2105. * @param string $attribute
  2106. * @param string $dir
  2107. * @return Mage_Catalog_Model_Resource_Product_Collection
  2108. */
  2109. public function setOrder($attribute, $dir = 'desc')
  2110. {
  2111. if ($attribute == 'price') {
  2112. $this->addAttributeToSort($attribute, $dir);
  2113. } else {
  2114. parent::setOrder($attribute, $dir);
  2115. }
  2116. return $this;
  2117. }
  2118.  
  2119. /**
  2120. * Get products max price
  2121. *
  2122. * @return float
  2123. */
  2124. public function getMaxPrice()
  2125. {
  2126. if (is_null($this->_maxPrice)) {
  2127. $this->_prepareStatisticsData();
  2128. }
  2129.  
  2130. return $this->_maxPrice;
  2131. }
  2132.  
  2133. /**
  2134. * Get products min price
  2135. *
  2136. * @return float
  2137. */
  2138. public function getMinPrice()
  2139. {
  2140. if (is_null($this->_minPrice)) {
  2141. $this->_prepareStatisticsData();
  2142. }
  2143.  
  2144. return $this->_minPrice;
  2145. }
  2146.  
  2147. /**
  2148. * Get standard deviation of products price
  2149. *
  2150. * @return float
  2151. */
  2152. public function getPriceStandardDeviation()
  2153. {
  2154. if (is_null($this->_priceStandardDeviation)) {
  2155. $this->_prepareStatisticsData();
  2156. }
  2157.  
  2158. return $this->_priceStandardDeviation;
  2159. }
  2160.  
  2161.  
  2162. /**
  2163. * Get count of product prices
  2164. *
  2165. * @return int
  2166. */
  2167. public function getPricesCount()
  2168. {
  2169. if (is_null($this->_pricesCount)) {
  2170. $this->_prepareStatisticsData();
  2171. }
  2172.  
  2173. return $this->_pricesCount;
  2174. }
  2175. }
RAW Paste Data