PageRenderTime 54ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 1ms

/app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Product/Collection.php

https://bitbucket.org/claudiu_marginean/magento-hg-mirror
PHP | 1861 lines | 1167 code | 195 blank | 499 comment | 180 complexity | 070594e8a137f1c4d06e7d25e0905016 MD5 | raw file
Possible License(s): CC-BY-SA-3.0, LGPL-2.1, GPL-2.0, WTFPL

Large files files are truncated, but you can click here to view the full file

  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) 2010 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. * Product collection
  28. *
  29. * @category Mage
  30. * @package Mage_Catalog
  31. * @author Magento Core Team <core@magentocommerce.com>
  32. */
  33. class Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection
  34. extends Mage_Catalog_Model_Resource_Eav_Mysql4_Collection_Abstract
  35. {
  36. /**
  37. * Catalog Product Flat is enabled cache per store
  38. *
  39. * @var array
  40. */
  41. protected $_flatEnabled = array();
  42. /**
  43. * Product websites table name
  44. *
  45. * @var string
  46. */
  47. protected $_productWebsiteTable;
  48. /**
  49. * Product categories table name
  50. *
  51. * @var string
  52. */
  53. protected $_productCategoryTable;
  54. /**
  55. * Is add URL rewrites to collection flag
  56. *
  57. * @var bool
  58. */
  59. protected $_addUrlRewrite = false;
  60. /**
  61. * Add URL rewrite for category
  62. *
  63. * @var int
  64. */
  65. protected $_urlRewriteCategory = '';
  66. /**
  67. * Is add minimal price to product collection flag
  68. *
  69. * @var bool
  70. */
  71. protected $_addMinimalPrice = false;
  72. /**
  73. * Is add final price to product collection flag
  74. *
  75. * @var unknown_type
  76. */
  77. protected $_addFinalPrice = false;
  78. /**
  79. * Cache for all ids
  80. *
  81. * @var array
  82. */
  83. protected $_allIdsCache = null;
  84. /**
  85. * Is add tax percents to product collection flag
  86. *
  87. * @var bool
  88. */
  89. protected $_addTaxPercents = false;
  90. /**
  91. * Product limitation filters
  92. *
  93. * Allowed filters
  94. * store_id int;
  95. * category_id int;
  96. * category_is_anchor int;
  97. * visibility array|int;
  98. * website_ids array|int;
  99. * store_table string;
  100. * use_price_index bool; join price index table flag
  101. * customer_group_id int; required for price; customer group limitation for price
  102. * website_id int; required for price; website limitation for price
  103. *
  104. * @var array
  105. */
  106. protected $_productLimitationFilters = array();
  107. /**
  108. * Category product count select
  109. *
  110. * @var Zend_Db_Select
  111. */
  112. protected $_productCountSelect = null;
  113. /**
  114. * @var bool
  115. */
  116. protected $_isWebsiteFilter = false;
  117. /**
  118. * Additional field filters, applied in _productLimitationJoinPrice()
  119. *
  120. * @var array
  121. */
  122. protected $_priceDataFieldFilters = array();
  123. /**
  124. * Map of price fields
  125. *
  126. * @var array
  127. */
  128. protected $_map = array('fields' => array(
  129. 'price' => 'price_index.price',
  130. 'final_price' => 'price_index.final_price',
  131. 'min_price' => 'price_index.min_price',
  132. 'max_price' => 'price_index.max_price',
  133. 'tier_price' => 'price_index.tier_price',
  134. 'special_price' => 'price_index.special_price',
  135. ));
  136. /**
  137. * Retrieve Catalog Product Flat Helper object
  138. *
  139. * @return Mage_Catalog_Helper_Product_Flat
  140. */
  141. public function getFlatHelper()
  142. {
  143. return Mage::helper('catalog/product_flat');
  144. }
  145. /**
  146. * Retrieve is flat enabled flag
  147. * Return alvays false if magento run admin
  148. *
  149. * @return bool
  150. */
  151. public function isEnabledFlat()
  152. {
  153. if (Mage::app()->getStore()->isAdmin()) {
  154. return false;
  155. }
  156. if (!isset($this->_flatEnabled[$this->getStoreId()])) {
  157. $this->_flatEnabled[$this->getStoreId()] = $this->getFlatHelper()
  158. ->isEnabled($this->getStoreId());
  159. }
  160. return $this->_flatEnabled[$this->getStoreId()];
  161. }
  162. /**
  163. * Initialize resources
  164. *
  165. */
  166. protected function _construct()
  167. {
  168. if ($this->isEnabledFlat()) {
  169. $this->_init('catalog/product', 'catalog/product_flat');
  170. }
  171. else {
  172. $this->_init('catalog/product');
  173. }
  174. $this->_initTables();
  175. }
  176. /**
  177. * Define product website and category product tables
  178. */
  179. protected function _initTables()
  180. {
  181. $this->_productWebsiteTable = $this->getResource()->getTable('catalog/product_website');
  182. $this->_productCategoryTable= $this->getResource()->getTable('catalog/category_product');
  183. }
  184. /**
  185. * Standard resource collection initalization
  186. *
  187. * @param string $model
  188. * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection
  189. */
  190. protected function _init($model, $entityModel=null)
  191. {
  192. if ($this->isEnabledFlat()) {
  193. $entityModel = 'catalog/product_flat';
  194. }
  195. return parent::_init($model, $entityModel);
  196. }
  197. /**
  198. * Prepare static entity fields
  199. *
  200. * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection
  201. */
  202. protected function _prepareStaticFields()
  203. {
  204. if ($this->isEnabledFlat()) {
  205. return $this;
  206. }
  207. return parent::_prepareStaticFields();
  208. }
  209. /**
  210. * Retrieve collection empty item
  211. * Redeclared for specifying id field name without getting resource model inside model
  212. *
  213. * @return Varien_Object
  214. */
  215. public function getNewEmptyItem()
  216. {
  217. $object = parent::getNewEmptyItem();
  218. if ($this->isEnabledFlat()) {
  219. $object->setIdFieldName($this->getEntity()->getIdFieldName());
  220. }
  221. return $object;
  222. }
  223. /**
  224. * Set entity to use for attributes
  225. *
  226. * @param Mage_Eav_Model_Entity_Abstract $entity
  227. * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection
  228. */
  229. public function setEntity($entity)
  230. {
  231. if ($this->isEnabledFlat() && ($entity instanceof Mage_Core_Model_Mysql4_Abstract)) {
  232. $this->_entity = $entity;
  233. return $this;
  234. }
  235. return parent::setEntity($entity);
  236. }
  237. /**
  238. * Set Store scope for collection
  239. *
  240. * @param mixed $store
  241. * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection
  242. */
  243. public function setStore($store)
  244. {
  245. parent::setStore($store);
  246. if ($this->isEnabledFlat()) {
  247. $this->getEntity()->setStoreId($this->getStoreId());
  248. }
  249. return $this;
  250. }
  251. /**
  252. * Initialize collection select
  253. * Redeclared for remove entity_type_id condition
  254. * in catalog_product_entity we store just products
  255. *
  256. * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection
  257. */
  258. protected function _initSelect()
  259. {
  260. if ($this->isEnabledFlat()) {
  261. $this->getSelect()
  262. ->from(array('e' => $this->getEntity()->getFlatTableName()), null)
  263. ->columns(array('status' => new Zend_Db_Expr(Mage_Catalog_Model_Product_Status::STATUS_ENABLED)));
  264. $this->addAttributeToSelect(array('entity_id', 'type_id', 'attribute_set_id'));
  265. if ($this->getFlatHelper()->isAddChildData()) {
  266. $this->getSelect()
  267. ->where('e.is_child=?', 0);
  268. $this->addAttributeToSelect(array('child_id', 'is_child'));
  269. }
  270. }
  271. else {
  272. $this->getSelect()->from(array('e'=>$this->getEntity()->getEntityTable()));
  273. }
  274. return $this;
  275. }
  276. /**
  277. * Load attributes into loaded entities
  278. *
  279. * @param bool $printQuery
  280. * @param bool $logQuery
  281. * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection
  282. */
  283. public function _loadAttributes($printQuery = false, $logQuery = false)
  284. {
  285. if ($this->isEnabledFlat()) {
  286. return $this;
  287. }
  288. return parent::_loadAttributes($printQuery, $logQuery);
  289. }
  290. /**
  291. * Add attribute to entities in collection
  292. *
  293. * If $attribute=='*' select all attributes
  294. *
  295. * @param array|string|integer|Mage_Core_Model_Config_Element $attribute
  296. * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection
  297. */
  298. public function addAttributeToSelect($attribute, $joinType = false)
  299. {
  300. if ($this->isEnabledFlat()) {
  301. if (!is_array($attribute)) {
  302. $attribute = array($attribute);
  303. }
  304. foreach ($attribute as $attributeCode) {
  305. if ($attributeCode == '*') {
  306. foreach ($this->getEntity()->getAllTableColumns() as $column) {
  307. $this->getSelect()->columns('e.'.$column);
  308. $this->_selectAttributes[$column] = $column;
  309. $this->_staticFields[$column] = $column;
  310. }
  311. }
  312. else {
  313. if ($columns = $this->getEntity()->getAttributeForSelect($attributeCode)) {
  314. foreach ($columns as $alias => $column) {
  315. $this->getSelect()->columns(array($alias => 'e.'.$column));
  316. $this->_selectAttributes[$column] = $column;
  317. $this->_staticFields[$column] = $column;
  318. }
  319. }
  320. }
  321. }
  322. return $this;
  323. }
  324. return parent::addAttributeToSelect($attribute, $joinType);
  325. }
  326. /**
  327. * Add tax class id attribute to select and join price rules data if needed
  328. *
  329. * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection
  330. */
  331. protected function _beforeLoad()
  332. {
  333. // if ($this->_addFinalPrice) {
  334. // $this->_joinPriceRules();
  335. // }
  336. Mage::dispatchEvent('catalog_product_collection_load_before', array('collection'=>$this));
  337. return parent::_beforeLoad();
  338. }
  339. /**
  340. * Processing collection items after loading
  341. * Adding url rewrites, minimal prices, final prices, tax percents
  342. *
  343. * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection
  344. */
  345. protected function _afterLoad()
  346. {
  347. if ($this->_addUrlRewrite) {
  348. $this->_addUrlRewrite($this->_urlRewriteCategory);
  349. }
  350. // if ($this->_addFinalPrice) {
  351. // $this->_addFinalPrice();
  352. // }
  353. $this->_prepareUrlDataObject();
  354. if (count($this) > 0) {
  355. Mage::dispatchEvent('catalog_product_collection_load_after', array('collection'=>$this));
  356. }
  357. foreach ($this as $product) {
  358. if ($product->isRecurring() && $profile = $product->getRecurringProfile()) {
  359. $product->setRecurringProfile(unserialize($profile));
  360. }
  361. // Mage::getSilgleton('catalog/product_attribute_backend_recurring')->afterLoad($product);
  362. }
  363. return $this;
  364. }
  365. /**
  366. * Prepare Url Data object
  367. *
  368. * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection
  369. */
  370. protected function _prepareUrlDataObject()
  371. {
  372. $objects = array();
  373. /* @var $item Mage_Catalog_Model_Product */
  374. foreach ($this->_items as $item) {
  375. if ($this->getFlag('do_not_use_category_id')) {
  376. $item->setDoNotUseCategoryId(true);
  377. }
  378. if (!$item->isVisibleInSiteVisibility() && $item->getItemStoreId()) {
  379. $objects[$item->getEntityId()] = $item->getItemStoreId();
  380. }
  381. }
  382. if ($objects && $this->hasFlag('url_data_object')) {
  383. $objects = Mage::getResourceSingleton('catalog/url')
  384. ->getRewriteByProductStore($objects);
  385. foreach ($this->_items as $item) {
  386. if (isset($objects[$item->getEntityId()])) {
  387. $object = new Varien_Object($objects[$item->getEntityId()]);
  388. $item->setUrlDataObject($object);
  389. }
  390. }
  391. }
  392. return $this;
  393. }
  394. /**
  395. * Add collection filters by identifiers
  396. *
  397. * @param mixed $productId
  398. * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection
  399. */
  400. public function addIdFilter($productId, $exclude = false)
  401. {
  402. if (empty($productId)) {
  403. $this->_setIsLoaded(true);
  404. return $this;
  405. }
  406. if (is_array($productId)) {
  407. if (!empty($productId)) {
  408. if ($exclude) {
  409. $condition = array('nin'=>$productId);
  410. } else {
  411. $condition = array('in'=>$productId);
  412. }
  413. }
  414. else {
  415. $condition = '';
  416. }
  417. }
  418. else {
  419. if ($exclude) {
  420. $condition = array('neq'=>$productId);
  421. } else {
  422. $condition = $productId;
  423. }
  424. }
  425. $this->addFieldToFilter('entity_id', $condition);
  426. return $this;
  427. }
  428. /**
  429. * Adding product website names to result collection
  430. * Add for each product websites information
  431. *
  432. * @return Mage_Catalog_Model_Entity_Product_Collection
  433. */
  434. public function addWebsiteNamesToResult()
  435. {
  436. $productStores = array();
  437. foreach ($this as $product) {
  438. $productWebsites[$product->getId()] = array();
  439. }
  440. if (!empty($productWebsites)) {
  441. $select = $this->getConnection()->select()
  442. ->from(array('product_website'=>$this->_productWebsiteTable))
  443. ->join(
  444. array('website'=>$this->getResource()->getTable('core/website')),
  445. 'website.website_id=product_website.website_id',
  446. array('name'))
  447. ->where($this->getConnection()->quoteInto(
  448. 'product_website.product_id IN (?)',
  449. array_keys($productWebsites))
  450. )
  451. ->where('website.website_id>0');
  452. $data = $this->getConnection()->fetchAll($select);
  453. foreach ($data as $row) {
  454. $productWebsites[$row['product_id']][] = $row['website_id'];
  455. }
  456. }
  457. foreach ($this as $product) {
  458. if (isset($productWebsites[$product->getId()])) {
  459. $product->setData('websites', $productWebsites[$product->getId()]);
  460. }
  461. }
  462. return $this;
  463. }
  464. /**
  465. * Add store availability filter. Include availability product
  466. * for store website
  467. *
  468. * @param mixed $store
  469. * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection
  470. */
  471. public function addStoreFilter($store=null)
  472. {
  473. if (is_null($store)) {
  474. $store = $this->getStoreId();
  475. }
  476. $store = Mage::app()->getStore($store);
  477. if (!$store->isAdmin()) {
  478. $this->setStoreId($store);
  479. $this->_productLimitationFilters['store_id'] = $store->getId();
  480. $this->_applyProductLimitations();
  481. }
  482. return $this;
  483. }
  484. /**
  485. * Add website filter to collection
  486. *
  487. * @param Mage_Core_Model_Website|int|string|array $website
  488. * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection
  489. */
  490. public function addWebsiteFilter($websites = null)
  491. {
  492. if (!is_array($websites)) {
  493. $websites = array(Mage::app()->getWebsite($websites)->getId());
  494. }
  495. $this->_productLimitationFilters['website_ids'] = $websites;
  496. $this->_applyProductLimitations();
  497. return $this;
  498. }
  499. /**
  500. * Specify category filter for product collection
  501. *
  502. * @param Mage_Catalog_Model_Category $category
  503. * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection
  504. */
  505. public function addCategoryFilter(Mage_Catalog_Model_Category $category)
  506. {
  507. $this->_productLimitationFilters['category_id'] = $category->getId();
  508. if ($category->getIsAnchor()) {
  509. unset($this->_productLimitationFilters['category_is_anchor']);
  510. } else {
  511. $this->_productLimitationFilters['category_is_anchor'] = 1;
  512. }
  513. if ($this->getStoreId() == Mage_Core_Model_App::ADMIN_STORE_ID) {
  514. $this->_applyZeroStoreProductLimitations();
  515. } else {
  516. $this->_applyProductLimitations();
  517. }
  518. return $this;
  519. }
  520. /**
  521. * Join minimal price attribute to result
  522. *
  523. * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection
  524. */
  525. public function joinMinimalPrice()
  526. {
  527. $this->addAttributeToSelect('price')
  528. ->addAttributeToSelect('minimal_price');
  529. return $this;
  530. }
  531. /**
  532. * Retrieve max value by attribute
  533. *
  534. * @param string $attribute
  535. * @return mixed
  536. */
  537. public function getMaxAttributeValue($attribute)
  538. {
  539. $select = clone $this->getSelect();
  540. $attribute = $this->getEntity()->getAttribute($attribute);
  541. $attributeCode = $attribute->getAttributeCode();
  542. $tableAlias = $attributeCode.'_max_value';
  543. $condition = 'e.entity_id='.$tableAlias.'.entity_id
  544. AND '.$this->_getConditionSql($tableAlias.'.attribute_id', $attribute->getId())
  545. //.' AND '.$this->_getConditionSql($tableAlias.'.store_id', $this->getEntity()->getStoreId())
  546. ;
  547. $select->join(
  548. array($tableAlias => $attribute->getBackend()->getTable()),
  549. $condition,
  550. array('max_'.$attributeCode=>new Zend_Db_Expr('MAX('.$tableAlias.'.value)'))
  551. )
  552. ->group('e.entity_type_id');
  553. $data = $this->getConnection()->fetchRow($select);
  554. if (isset($data['max_'.$attributeCode])) {
  555. return $data['max_'.$attributeCode];
  556. }
  557. return null;
  558. }
  559. /**
  560. * Retrieve ranging product count for arrtibute range
  561. *
  562. * @param string $attribute
  563. * @param int $range
  564. * @return array
  565. */
  566. public function getAttributeValueCountByRange($attribute, $range)
  567. {
  568. $select = clone $this->getSelect();
  569. $attribute = $this->getEntity()->getAttribute($attribute);
  570. $attributeCode = $attribute->getAttributeCode();
  571. $tableAlias = $attributeCode.'_range_count_value';
  572. $condition = 'e.entity_id='.$tableAlias.'.entity_id
  573. AND '.$this->_getConditionSql($tableAlias.'.attribute_id', $attribute->getId())
  574. //.' AND '.$this->_getConditionSql($tableAlias.'.store_id', $this->getEntity()->getStoreId())
  575. ;
  576. $select->reset(Zend_Db_Select::GROUP);
  577. $select->join(
  578. array($tableAlias => $attribute->getBackend()->getTable()),
  579. $condition,
  580. array(
  581. 'count_'.$attributeCode=>new Zend_Db_Expr('COUNT(DISTINCT e.entity_id)'),
  582. 'range_'.$attributeCode=>new Zend_Db_Expr('CEIL(('.$tableAlias.'.value+0.01)/'.$range.')')
  583. )
  584. )
  585. ->group('range_'.$attributeCode);
  586. $data = $this->getConnection()->fetchAll($select);
  587. $res = array();
  588. foreach ($data as $row) {
  589. $res[$row['range_'.$attributeCode]] = $row['count_'.$attributeCode];
  590. }
  591. return $res;
  592. }
  593. /**
  594. * Retrieve product count by some value of attribute
  595. *
  596. * @param string $attribute
  597. * @return array($value=>$count)
  598. */
  599. public function getAttributeValueCount($attribute)
  600. {
  601. $select = clone $this->getSelect();
  602. $attribute = $this->getEntity()->getAttribute($attribute);
  603. $attributeCode = $attribute->getAttributeCode();
  604. $tableAlias = $attributeCode.'_value_count';
  605. $select->reset(Zend_Db_Select::GROUP);
  606. $condition = 'e.entity_id='.$tableAlias.'.entity_id
  607. AND '.$this->_getConditionSql($tableAlias.'.attribute_id', $attribute->getId())
  608. //.' AND '.$this->_getConditionSql($tableAlias.'.store_id', $this->getEntity()->getStoreId())
  609. ;
  610. $select->join(
  611. array($tableAlias => $attribute->getBackend()->getTable()),
  612. $condition,
  613. array(
  614. 'count_'.$attributeCode=>new Zend_Db_Expr('COUNT(DISTINCT e.entity_id)'),
  615. 'value_'.$attributeCode=>new Zend_Db_Expr($tableAlias.'.value')
  616. )
  617. )
  618. ->group('value_'.$attributeCode);
  619. $data = $this->getConnection()->fetchAll($select);
  620. $res = array();
  621. foreach ($data as $row) {
  622. $res[$row['value_'.$attributeCode]] = $row['count_'.$attributeCode];
  623. }
  624. return $res;
  625. }
  626. /**
  627. * Return all attribute values as array in form:
  628. * array(
  629. * [entity_id_1] => array(
  630. * [store_id_1] => store_value_1,
  631. * [store_id_2] => store_value_2,
  632. * ...
  633. * [store_id_n] => store_value_n
  634. * ),
  635. * ...
  636. * )
  637. *
  638. * @param string $attribute attribute code
  639. * @return array
  640. */
  641. public function getAllAttributeValues($attribute)
  642. {
  643. /** @var Zend_Db_Select */
  644. $select = clone $this->getSelect();
  645. $attribute = $this->getEntity()->getAttribute($attribute);
  646. $select->reset()
  647. ->from($attribute->getBackend()->getTable(), array('entity_id', 'store_id', 'value'))
  648. ->where('attribute_id = ?', $attribute->getId(), Zend_Db::INT_TYPE);
  649. $data = $this->getConnection()->fetchAll($select);
  650. $res = array();
  651. foreach ($data as $row) {
  652. $res[$row['entity_id']][$row['store_id']] = $row['value'];
  653. }
  654. return $res;
  655. }
  656. /**
  657. * Get SQL for get record count
  658. *
  659. * @return Varien_Db_Select
  660. */
  661. public function getSelectCountSql()
  662. {
  663. $this->_renderFilters();
  664. $countSelect = clone $this->getSelect();
  665. $countSelect->reset(Zend_Db_Select::ORDER);
  666. $countSelect->reset(Zend_Db_Select::LIMIT_COUNT);
  667. $countSelect->reset(Zend_Db_Select::LIMIT_OFFSET);
  668. $countSelect->reset(Zend_Db_Select::COLUMNS);
  669. $countSelect->columns('COUNT(DISTINCT e.entity_id)');
  670. $countSelect->resetJoinLeft();
  671. return $countSelect;
  672. }
  673. /**
  674. * Retrive all ids for collection
  675. *
  676. * @return array
  677. */
  678. public function getAllIds($limit=null, $offset=null)
  679. {
  680. $idsSelect = clone $this->getSelect();
  681. $idsSelect->reset(Zend_Db_Select::ORDER);
  682. $idsSelect->reset(Zend_Db_Select::LIMIT_COUNT);
  683. $idsSelect->reset(Zend_Db_Select::LIMIT_OFFSET);
  684. $idsSelect->reset(Zend_Db_Select::COLUMNS);
  685. $idsSelect->columns('e.'.$this->getEntity()->getIdFieldName());
  686. $idsSelect->limit($limit, $offset);
  687. $idsSelect->resetJoinLeft();
  688. return $this->getConnection()->fetchCol($idsSelect, $this->_bindParams);
  689. }
  690. /**
  691. * Retreive product count select for categories
  692. *
  693. * @return Varien_Db_Select
  694. */
  695. public function getProductCountSelect()
  696. {
  697. if ($this->_productCountSelect === null) {
  698. $this->_productCountSelect = clone $this->getSelect();
  699. $this->_productCountSelect->reset(Zend_Db_Select::COLUMNS)
  700. ->reset(Zend_Db_Select::GROUP)
  701. ->reset(Zend_Db_Select::ORDER)
  702. ->distinct(false)
  703. ->join(array('count_table' => $this->getTable('catalog/category_product_index')),
  704. 'count_table.product_id = e.entity_id',
  705. array(
  706. 'count_table.category_id',
  707. 'product_count' => new Zend_Db_Expr('COUNT(DISTINCT count_table.product_id)')
  708. )
  709. )
  710. ->where('count_table.store_id = ?', $this->getStoreId())
  711. ->group('count_table.category_id');
  712. }
  713. return $this->_productCountSelect;
  714. }
  715. /**
  716. * Destruct product count select
  717. *
  718. * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection
  719. */
  720. public function unsProductCountSelect()
  721. {
  722. $this->_productCountSelect = null;
  723. return $this;
  724. }
  725. /**
  726. * Adding product count to categories collection
  727. *
  728. * @param Mage_Eav_Model_Entity_Collection_Abstract $categoryCollection
  729. * @return Mage_Eav_Model_Entity_Collection_Abstract
  730. */
  731. public function addCountToCategories($categoryCollection)
  732. {
  733. $isAnchor = array();
  734. $isNotAnchor = array();
  735. foreach ($categoryCollection as $category) {
  736. if ($category->getIsAnchor()) {
  737. $isAnchor[] = $category->getId();
  738. } else {
  739. $isNotAnchor[] = $category->getId();
  740. }
  741. }
  742. $productCounts = array();
  743. if ($isAnchor || $isNotAnchor) {
  744. $select = $this->getProductCountSelect();
  745. Mage::dispatchEvent(
  746. 'catalog_product_collection_before_add_count_to_categories',
  747. array('collection' => $this)
  748. );
  749. if ($isAnchor) {
  750. $anchorStmt = clone $select;
  751. $anchorStmt->limit(); //reset limits
  752. $anchorStmt->where('count_table.category_id in (?)', $isAnchor);
  753. $productCounts += $this->getConnection()->fetchPairs($anchorStmt);
  754. $anchorStmt = null;
  755. }
  756. if ($isNotAnchor) {
  757. $notAnchorStmt = clone $select;
  758. $notAnchorStmt->limit(); //reset limits
  759. $notAnchorStmt->where('count_table.category_id in (?)', $isNotAnchor);
  760. $notAnchorStmt->where('count_table.is_parent=1');
  761. $productCounts += $this->getConnection()->fetchPairs($notAnchorStmt);
  762. $notAnchorStmt = null;
  763. }
  764. $select = null;
  765. $this->unsProductCountSelect();
  766. }
  767. foreach ($categoryCollection as $category) {
  768. $_count = 0;
  769. if (isset($productCounts[$category->getId()])) {
  770. $_count = $productCounts[$category->getId()];
  771. }
  772. $category->setProductCount($_count);
  773. }
  774. // foreach ($categoryCollection as $category) {
  775. // $select = clone $this->getSelect();
  776. // $select->reset(Zend_Db_Select::COLUMNS);
  777. // $select->reset(Zend_Db_Select::GROUP);
  778. // $select->reset(Zend_Db_Select::ORDER);
  779. // $select->distinct(false);
  780. // $select->join(
  781. // array('category_count_table' => $this->_productCategoryTable),
  782. // 'category_count_table.product_id=e.entity_id',
  783. // array('count_in_category'=>new Zend_Db_Expr('COUNT(DISTINCT e.entity_id)'))
  784. // );
  785. //
  786. // if ($category->getIsAnchor()) {
  787. // $select->where($this->getConnection()->quoteInto(
  788. // 'category_count_table.category_id IN(?)',
  789. // explode(',', $category->getAllChildren())
  790. // ));
  791. // }
  792. // else {
  793. // $select->where($this->getConnection()->quoteInto(
  794. // 'category_count_table.category_id=?',
  795. // $category->getId()
  796. // ));
  797. // }
  798. // $category->setProductCount((int) $this->getConnection()->fetchOne($select));
  799. // }
  800. return $this;
  801. }
  802. public function getSetIds()
  803. {
  804. $select = clone $this->getSelect();
  805. /* @var $select Zend_Db_Select */
  806. $select->reset(Zend_Db_Select::COLUMNS);
  807. $select->distinct(true);
  808. $select->columns('attribute_set_id');
  809. return $this->getConnection()->fetchCol($select);
  810. }
  811. /**
  812. * Return array of unique product type ids in collection
  813. *
  814. * @return array
  815. */
  816. public function getProductTypeIds()
  817. {
  818. $select = clone $this->getSelect();
  819. /* @var $select Zend_Db_Select */
  820. $select->reset(Zend_Db_Select::COLUMNS);
  821. $select->distinct(true);
  822. $select->columns('type_id');
  823. return $this->getConnection()->fetchCol($select);
  824. }
  825. /**
  826. * Joins url rewrite rules to collection
  827. *
  828. * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Category_Collection
  829. */
  830. public function joinUrlRewrite()
  831. {
  832. $this->joinTable(
  833. 'core/url_rewrite',
  834. 'entity_id=entity_id',
  835. array('request_path'),
  836. '{{table}}.type='.Mage_Core_Model_Url_Rewrite::TYPE_PRODUCT,
  837. 'left'
  838. );
  839. return $this;
  840. }
  841. /**
  842. * Add URL rewrites data to product
  843. * If collection loadded - run processing else set flag
  844. *
  845. * @param int $categoryId
  846. * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection
  847. */
  848. public function addUrlRewrite($categoryId = '')
  849. {
  850. $this->_addUrlRewrite = true;
  851. if (Mage::getStoreConfig(Mage_Catalog_Helper_Product::XML_PATH_PRODUCT_URL_USE_CATEGORY, $this->getStoreId())) {
  852. $this->_urlRewriteCategory = $categoryId;
  853. } else {
  854. $this->_urlRewriteCategory = 0;
  855. }
  856. if ($this->isLoaded()) {
  857. $this->_addUrlRewrite();
  858. }
  859. return $this;
  860. }
  861. /**
  862. * Add URL rewrites to collection
  863. *
  864. */
  865. protected function _addUrlRewrite()
  866. {
  867. $urlRewrites = null;
  868. if ($this->_cacheConf) {
  869. if (!($urlRewrites = Mage::app()->loadCache($this->_cacheConf['prefix'].'urlrewrite'))) {
  870. $urlRewrites = null;
  871. } else {
  872. $urlRewrites = unserialize($urlRewrites);
  873. }
  874. }
  875. if (!$urlRewrites) {
  876. $productIds = array();
  877. foreach($this->getItems() as $item) {
  878. $productIds[] = $item->getEntityId();
  879. }
  880. if (!count($productIds)) {
  881. return;
  882. }
  883. $select = $this->getConnection()->select()
  884. ->from($this->getTable('core/url_rewrite'), array('product_id', 'request_path'))
  885. ->where('store_id=?', Mage::app()->getStore()->getId())
  886. ->where('is_system=?', 1)
  887. ->where('category_id=? OR category_id is NULL', $this->_urlRewriteCategory)
  888. ->where('product_id IN(?)', $productIds)
  889. ->order('category_id DESC'); // more priority is data with category id
  890. $urlRewrites = array();
  891. foreach ($this->getConnection()->fetchAll($select) as $row) {
  892. if (!isset($urlRewrites[$row['product_id']])) {
  893. $urlRewrites[$row['product_id']] = $row['request_path'];
  894. }
  895. }
  896. if ($this->_cacheConf) {
  897. Mage::app()->saveCache(
  898. serialize($urlRewrites),
  899. $this->_cacheConf['prefix'].'urlrewrite',
  900. array_merge($this->_cacheConf['tags'], array(Mage_Catalog_Model_Product_Url::CACHE_TAG)),
  901. $this->_cacheLifetime
  902. );
  903. }
  904. }
  905. foreach($this->getItems() as $item) {
  906. if (isset($urlRewrites[$item->getEntityId()])) {
  907. $item->setData('request_path', $urlRewrites[$item->getEntityId()]);
  908. } else {
  909. $item->setData('request_path', false);
  910. }
  911. }
  912. }
  913. /**
  914. * Add minimal price data to result
  915. *
  916. * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection
  917. */
  918. public function addMinimalPrice()
  919. {
  920. return $this->addPriceData();
  921. }
  922. /**
  923. * Add minimal price to product collection
  924. *
  925. * @deprecated sinse 1.3.2.2
  926. * @see Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection::addPriceData
  927. * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection
  928. */
  929. protected function _addMinimalPrice()
  930. {
  931. return $this;
  932. }
  933. /**
  934. * Add price data for calculate final price
  935. *
  936. * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection
  937. */
  938. public function addFinalPrice()
  939. {
  940. return $this->addPriceData();
  941. }
  942. /**
  943. * Join prices from price rules to products collection
  944. *
  945. * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection
  946. */
  947. protected function _joinPriceRules()
  948. {
  949. if ($this->isEnabledFlat()) {
  950. $customerGroup = Mage::getSingleton('customer/session')->getCustomerGroupId();
  951. $priceColumn = 'e.display_price_group_' . $customerGroup;
  952. $this->getSelect()->columns(array('_rule_price' => $priceColumn));
  953. return $this;
  954. }
  955. $wId = Mage::app()->getStore($this->getStoreId())->getWebsite()->getId();
  956. $gId = Mage::getSingleton('customer/session')->getCustomerGroupId();
  957. $storeDate = Mage::app()->getLocale()->storeTimeStamp($this->getStoreId());
  958. $conditions = "_price_rule.product_id = e.entity_id AND ";
  959. $conditions .= "_price_rule.rule_date = '".$this->getResource()->formatDate($storeDate, false)."' AND ";
  960. $conditions .= "_price_rule.website_id = '{$wId}' AND ";
  961. $conditions .= "_price_rule.customer_group_id = '{$gId}'";
  962. $this->getSelect()->joinLeft(
  963. array('_price_rule'=>$this->getTable('catalogrule/rule_product_price')),
  964. $conditions,
  965. array('_rule_price'=>'rule_price')
  966. );
  967. return $this;
  968. }
  969. protected function _addFinalPrice()
  970. {
  971. foreach ($this->_items as $product) {
  972. $basePrice = $product->getPrice();
  973. $specialPrice = $product->getSpecialPrice();
  974. $specialPriceFrom = $product->getSpecialFromDate();
  975. $specialPriceTo = $product->getSpecialToDate();
  976. if ($this->isEnabledFlat()) {
  977. $rulePrice = null;
  978. if ($product->getData('_rule_price') != $basePrice) {
  979. $rulePrice = $product->getData('_rule_price');
  980. }
  981. }
  982. else {
  983. $rulePrice = $product->getData('_rule_price');
  984. }
  985. $finalPrice = $product->getPriceModel()->calculatePrice(
  986. $basePrice,
  987. $specialPrice,
  988. $specialPriceFrom,
  989. $specialPriceTo,
  990. $rulePrice,
  991. null,
  992. null,
  993. $product->getId()
  994. );
  995. $product->setCalculatedFinalPrice($finalPrice);
  996. }
  997. }
  998. public function getAllIdsCache($resetCache = false)
  999. {
  1000. $ids = null;
  1001. if (!$resetCache) {
  1002. $ids = $this->_allIdsCache;
  1003. }
  1004. if (is_null($ids)) {
  1005. $ids = $this->getAllIds();
  1006. $this->setAllIdsCache($ids);
  1007. }
  1008. return $ids;
  1009. }
  1010. public function setAllIdsCache($value)
  1011. {
  1012. $this->_allIdsCache = $value;
  1013. return $this;
  1014. }
  1015. /**
  1016. * Add Price Data to result
  1017. *
  1018. * @param int $customerGroupId
  1019. * @param int $websiteId
  1020. * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection
  1021. */
  1022. public function addPriceData($customerGroupId = null, $websiteId = null)
  1023. {
  1024. $this->_productLimitationFilters['use_price_index'] = true;
  1025. if (!isset($this->_productLimitationFilters['customer_group_id']) && is_null($customerGroupId)) {
  1026. $customerGroupId = Mage::getSingleton('customer/session')->getCustomerGroupId();
  1027. }
  1028. if (!isset($this->_productLimitationFilters['website_id']) && is_null($websiteId)) {
  1029. $websiteId = Mage::app()->getStore($this->getStoreId())->getWebsiteId();
  1030. }
  1031. if (!is_null($customerGroupId)) {
  1032. $this->_productLimitationFilters['customer_group_id'] = $customerGroupId;
  1033. }
  1034. if (!is_null($websiteId)) {
  1035. $this->_productLimitationFilters['website_id'] = $websiteId;
  1036. }
  1037. $this->_applyProductLimitations();
  1038. return $this;
  1039. }
  1040. /**
  1041. * Add attribute to filter
  1042. *
  1043. * @param Mage_Eav_Model_Entity_Attribute_Abstract|string $attribute
  1044. * @param array $condition
  1045. * @param string $joinType
  1046. * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection
  1047. */
  1048. public function addAttributeToFilter($attribute, $condition=null, $joinType='inner')
  1049. {
  1050. if ($this->isEnabledFlat()) {
  1051. if ($attribute instanceof Mage_Eav_Model_Entity_Attribute_Abstract) {
  1052. $attribute = $attribute->getAttributeCode();
  1053. }
  1054. if (is_array($attribute)) {
  1055. $sqlArr = array();
  1056. foreach ($attribute as $condition) {
  1057. $sqlArr[] = $this->_getAttributeConditionSql($condition['attribute'], $condition, $joinType);
  1058. }
  1059. $conditionSql = '('.join(') OR (', $sqlArr).')';
  1060. $this->getSelect()->where($conditionSql, null, Varien_Db_Select::TYPE_CONDITION);
  1061. return $this;
  1062. }
  1063. if (!isset($this->_selectAttributes[$attribute])) {
  1064. $this->addAttributeToSelect($attribute);
  1065. }
  1066. if (isset($this->_selectAttributes[$attribute])) {
  1067. $this->getSelect()->where($this->_getConditionSql('e.'.$attribute, $condition));
  1068. }
  1069. return $this;
  1070. }
  1071. $this->_allIdsCache = null;
  1072. if (is_string($attribute) && $attribute == 'is_saleable') {
  1073. $columns = $this->getSelect()->getPart(Zend_Db_Select::COLUMNS);
  1074. foreach ($columns as $columnEntry) {
  1075. list($correlationName, $column, $alias) = $columnEntry;
  1076. if ($alias == 'is_saleable') {
  1077. if ($column instanceof Zend_Db_Expr) {
  1078. $field = $column;
  1079. } else {
  1080. $adapter = $this->getSelect()->getAdapter();
  1081. if (empty($correlationName)) {
  1082. $field = $adapter->quoteColumnAs($column, $alias, true);
  1083. } else {
  1084. $field = $adapter->quoteColumnAs(array($correlationName, $column), $alias, true);
  1085. }
  1086. }
  1087. $this->getSelect()->where("{$field} = ?", $condition);
  1088. break;
  1089. }
  1090. }
  1091. return $this;
  1092. } else {
  1093. return parent::addAttributeToFilter($attribute, $condition, $joinType);
  1094. }
  1095. }
  1096. /**
  1097. * Add requere tax percent flag for product collection
  1098. *
  1099. * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection
  1100. */
  1101. public function addTaxPercents()
  1102. {
  1103. $this->_addTaxPercents = true;
  1104. return $this;
  1105. }
  1106. /**
  1107. * Get require tax percent flag value
  1108. *
  1109. * @return bool
  1110. */
  1111. public function requireTaxPercent()
  1112. {
  1113. return $this->_addTaxPercents;
  1114. }
  1115. /**
  1116. * @deprecated from 1.3.0
  1117. */
  1118. protected function _addTaxPercents()
  1119. {
  1120. $classToRate = array();
  1121. $request = Mage::getSingleton('tax/calculation')->getRateRequest();
  1122. foreach ($this as &$item) {
  1123. if (null === $item->getTaxClassId()) {
  1124. $item->setTaxClassId($item->getMinimalTaxClassId());
  1125. }
  1126. if (!isset($classToRate[$item->getTaxClassId()])) {
  1127. $request->setProductClassId($item->getTaxClassId());
  1128. $classToRate[$item->getTaxClassId()] = Mage::getSingleton('tax/calculation')->getRate($request);
  1129. }
  1130. $item->setTaxPercent($classToRate[$item->getTaxClassId()]);
  1131. }
  1132. }
  1133. /**
  1134. * Adding product custom options to result collection
  1135. *
  1136. * @return Mage_Catalog_Model_Entity_Product_Collection
  1137. */
  1138. public function addOptionsToResult()
  1139. {
  1140. $productIds = array();
  1141. foreach ($this as $product) {
  1142. $productIds[] = $product->getId();
  1143. }
  1144. if (!empty($productIds)) {
  1145. $options = Mage::getModel('catalog/product_option')
  1146. ->getCollection()
  1147. ->addTitleToResult(Mage::app()->getStore()->getId())
  1148. ->addPriceToResult(Mage::app()->getStore()->getId())
  1149. ->addProductToFilter($productIds)
  1150. ->addValuesToResult();
  1151. foreach ($options as $option) {
  1152. if($this->getItemById($option->getProductId())) {
  1153. $this->getItemById($option->getProductId())->addOption($option);
  1154. }
  1155. }
  1156. }
  1157. return $this;
  1158. }
  1159. /**
  1160. * Filter products with required options
  1161. *
  1162. * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection
  1163. */
  1164. public function addFilterByRequiredOptions()
  1165. {
  1166. $this->addAttributeToFilter('required_options', array(array('neq'=>'1'), array('null'=>true)), 'left');
  1167. return $this;
  1168. }
  1169. /**
  1170. * Set product visibility filter for enabled products
  1171. *
  1172. * @param array $visibility
  1173. * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection
  1174. */
  1175. public function setVisibility($visibility)
  1176. {
  1177. $this->_productLimitationFilters['visibility'] = $visibility;
  1178. $this->_applyProductLimitations();
  1179. return $this;
  1180. }
  1181. /**
  1182. * Add attribute to sort order
  1183. *
  1184. * @param string $attribute
  1185. * @param string $dir
  1186. * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection
  1187. */
  1188. public function addAttributeToSort($attribute, $dir='asc')
  1189. {
  1190. if ($attribute == 'position') {
  1191. if (isset($this->_joinFields[$attribute])) {
  1192. $this->getSelect()->order("{$attribute} {$dir}");
  1193. return $this;
  1194. }
  1195. $this->getSelect()->order("cat_index_position {$dir}");
  1196. // optimize if using cat index
  1197. $filters = $this->_productLimitationFilters;
  1198. if (isset($filters['category_id']) || isset($filters['visibility'])) {
  1199. $this->getSelect()->order('cat_index.product_id ' . $dir);
  1200. }
  1201. else {
  1202. $this->getSelect()->order('e.entity_id ' . $dir);
  1203. }
  1204. return $this;
  1205. } else if($attribute == 'is_saleable'){
  1206. $this->getSelect()->order("is_saleable " . $dir);
  1207. return $this;
  1208. }
  1209. $storeId = Mage::app()->getStore()->getId();
  1210. if ($attribute == 'price' && $storeId != 0) {
  1211. $this->addPriceData();
  1212. $this->getSelect()->order("price_index.min_price {$dir}");
  1213. return $this;
  1214. }
  1215. if ($this->isEnabledFlat()) {
  1216. $column = $this->getEntity()->getAttributeSortColumn($attribute);
  1217. if ($column) {
  1218. $this->getSelect()->order("e.{$column} {$dir}");
  1219. }
  1220. else if (isset($this->_joinFields[$attribute])) {
  1221. $this->getSelect()->order($this->_getAttributeFieldName($attribute).' '.$dir);
  1222. }
  1223. return $this;
  1224. } else {
  1225. $attrInstance = $this->getEntity()->getAttribute($attribute);
  1226. if ($attrInstance && $attrInstance->usesSource()) {
  1227. $attrInstance->getSource()
  1228. ->addValueSortToCollection($this, $dir);
  1229. return $this;
  1230. }
  1231. }
  1232. return parent::addAttributeToSort($attribute, $dir);
  1233. }
  1234. /**
  1235. * Prepare limitation filters
  1236. *
  1237. * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection
  1238. */
  1239. protected function _prepareProductLimitationFilters()
  1240. {
  1241. if (isset($this->_productLimitationFilters['visibility'])
  1242. && !isset($this->_productLimitationFilters['store_id'])
  1243. ) {
  1244. $this->_productLimitationFilters['store_id'] = $this->getStoreId();
  1245. }
  1246. if (isset($this->_productLimitationFilters['category_id'])
  1247. && !isset($this->_productLimitationFilters['store_id'])
  1248. ) {
  1249. $this->_productLimitationFilters['store_id'] = $this->getStoreId();
  1250. }
  1251. if (isset($this->_productLimitationFilters['store_id'])
  1252. && isset($this->_productLimitationFilters['visibility'])
  1253. && !isset($this->_productLimitationFilters['category_id'])
  1254. ) {
  1255. $this->_productLimitationFilters['category_id'] = Mage::app()
  1256. ->getStore($this->_productLimitationFilters['store_id'])
  1257. ->getRootCategoryId();
  1258. }
  1259. return $this;
  1260. }
  1261. /**
  1262. * Join website product limitation
  1263. *
  1264. * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection
  1265. */
  1266. protected function _productLimitationJoinWebsite()
  1267. {
  1268. $joinWebsite = false;
  1269. $filters = $this->_productLimitationFilters;
  1270. $conditions = array(
  1271. 'product_website.product_id=e.entity_id'
  1272. );
  1273. if (isset($filters['website_ids'])) {
  1274. $joinWebsite = true;
  1275. if (count($filters['website_ids']) > 1) {
  1276. $this->getSelect()->distinct(true);
  1277. }
  1278. $conditions[] = $this->getConnection()
  1279. ->quoteInto('product_website.website_id IN(?)', $filters['website_ids']);
  1280. }
  1281. elseif (isset($filters['store_id'])
  1282. && (!isset($filters['visibility']) && !isset($filters['category_id']))
  1283. && !$this->isEnabledFlat()
  1284. ) {
  1285. $joinWebsite = true;
  1286. $websiteId = Mage::app()->getStore($filters['store_id'])->getWebsiteId();
  1287. $conditions[] = $this->getConnection()
  1288. ->quoteInto('product_website.website_id=?', $websiteId);
  1289. }
  1290. $fromPart = $this->getSelect()->getPart(Zend_Db_Select::FROM);
  1291. if (isset($fromPart['product_website'])) {
  1292. if (!$joinWebsite) {
  1293. unset($fromPart['product_website']);
  1294. }
  1295. else {
  1296. $fromPart['product_website']['joinCondition'] = join(' AND ', $conditions);
  1297. }
  1298. $this->getSelect()->setPart(Zend_Db_Select::FROM, $fromPart);
  1299. }
  1300. elseif ($joinWebsite) {
  1301. $this->getSelect()->join(
  1302. array('product_website' => $this->getTable('catalog/product_website')),
  1303. join(' AND ', $conditions),
  1304. array()
  1305. );
  1306. }
  1307. return $this;
  1308. }
  1309. /**
  1310. * Join additional (alternative) store visibility filter
  1311. *
  1312. * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection
  1313. */
  1314. protected function _productLimitationJoinStore()
  1315. {
  1316. $filters = $this->_productLimitationFilters;
  1317. if (!isset($filters['store_table'])) {
  1318. return $this;
  1319. }
  1320. $hasColumn = false;
  1321. foreach ($this->getSelect()->getPart(Zend_Db_Select::COLUMNS) as $columnEntry) {
  1322. list(,,$alias) = $columnEntry;
  1323. if ($alias == 'visibility') {
  1324. $hasColumn = true;
  1325. }
  1326. }
  1327. if (!$hasColumn) {
  1328. $this->getSelect()->columns('visibility', 'cat_index');
  1329. }
  1330. $fromPart = $this->getSelect()->getPart(Zend_Db_Select::FROM);
  1331. if (!isset($fromPart['store_index'])) {
  1332. $this->getSelect()->joinLeft(
  1333. array('store_index' => $this->getTable('core/store')),
  1334. 'store_index.store_id='.$filters['store_table'].'.store_id',
  1335. array()
  1336. );
  1337. }
  1338. if (!isset($fromPart['store_group_index'])) {
  1339. $this->getSelect()->joinLeft(
  1340. array('store_group_index' => $this->getTable('core/store_group')),
  1341. 'store_index.group_id=store_group_index.group_id',
  1342. array()
  1343. );
  1344. }
  1345. if (!isset($fromPart['store_cat_index'])) {
  1346. $this->getSelect()->joinLeft(
  1347. array('store_cat_index' => $this->getTable('catalog/category_product_index')),
  1348. join(' AND ', array(
  1349. 'store_cat_index.product_id=e.entity_id',
  1350. 'store_cat_index.store_id='.$filters['store_table'].'.store_id',
  1351. 'store_cat_index.category_id=store_group_index.root_category_id'
  1352. )),
  1353. array('store_visibility' => 'visibility')
  1354. );
  1355. }
  1356. $whereCond = join(' OR ', array(
  1357. $this->getConnection()->quoteInto('cat_index.visibility IN(?)', $filters['visibility']),
  1358. $this->getConnection()->quoteInto('store_cat_index.visibility IN(?)', $filters['visibility'])
  1359. ));
  1360. $wherePart = $this->getSelect()->getPart(Zend_Db_Select::WHERE);
  1361. $hasCond = false;
  1362. foreach ($wherePart as $cond) {
  1363. if ($cond == '('.$whereCond.')') {
  1364. $hasCond = true;
  1365. }
  1366. }
  1367. if (!$hasCond) {
  1368. $this->getSelect()->where($whereCond);
  1369. }
  1370. return $this;
  1371. }
  1372. /**

Large files files are truncated, but you can click here to view the full file