1: <?php
2: /**
3: * Magento
4: *
5: * NOTICE OF LICENSE
6: *
7: * This source file is subject to the Open Software License (OSL 3.0)
8: * that is bundled with this package in the file LICENSE.txt.
9: * It is also available through the world-wide-web at this URL:
10: * http://opensource.org/licenses/osl-3.0.php
11: * If you did not receive a copy of the license and are unable to
12: * obtain it through the world-wide-web, please send an email
13: * to license@magentocommerce.com so we can send you a copy immediately.
14: *
15: * DISCLAIMER
16: *
17: * Do not edit or add to this file if you wish to upgrade Magento to newer
18: * versions in the future. If you wish to customize Magento for your
19: * needs please refer to http://www.magentocommerce.com for more information.
20: *
21: * @category Mage
22: * @package Mage_Catalog
23: * @copyright Copyright (c) 2012 Magento Inc. (http://www.magentocommerce.com)
24: * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
25: */
26:
27:
28: /**
29: * Catalog view layer model
30: *
31: * @category Mage
32: * @package Mage_Catalog
33: * @author Magento Core Team <core@magentocommerce.com>
34: */
35: class Mage_Catalog_Model_Layer extends Varien_Object
36: {
37: /**
38: * Product collections array
39: *
40: * @var array
41: */
42: protected $_productCollections = array();
43:
44: /**
45: * Key which can be used for load/save aggregation data
46: *
47: * @var string
48: */
49: protected $_stateKey = null;
50:
51: /**
52: * Get data aggregation object
53: *
54: * @return Mage_CatalogIndex_Model_Aggregation
55: */
56: public function getAggregator()
57: {
58: return Mage::getSingleton('catalogindex/aggregation');
59: }
60:
61: /**
62: * Get layer state key
63: *
64: * @return string
65: */
66: public function getStateKey()
67: {
68: if ($this->_stateKey === null) {
69: $this->_stateKey = 'STORE_'.Mage::app()->getStore()->getId()
70: . '_CAT_' . $this->getCurrentCategory()->getId()
71: . '_CUSTGROUP_' . Mage::getSingleton('customer/session')->getCustomerGroupId();
72: }
73:
74: return $this->_stateKey;
75: }
76:
77: /**
78: * Get default tags for current layer state
79: *
80: * @param array $additionalTags
81: * @return array
82: */
83: public function getStateTags(array $additionalTags = array())
84: {
85: $additionalTags = array_merge($additionalTags, array(
86: Mage_Catalog_Model_Category::CACHE_TAG.$this->getCurrentCategory()->getId()
87: ));
88:
89: return $additionalTags;
90: }
91:
92: /**
93: * Retrieve current layer product collection
94: *
95: * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection
96: */
97: public function getProductCollection()
98: {
99: if (isset($this->_productCollections[$this->getCurrentCategory()->getId()])) {
100: $collection = $this->_productCollections[$this->getCurrentCategory()->getId()];
101: } else {
102: $collection = $this->getCurrentCategory()->getProductCollection();
103: $this->prepareProductCollection($collection);
104: $this->_productCollections[$this->getCurrentCategory()->getId()] = $collection;
105: }
106:
107: return $collection;
108: }
109:
110: /**
111: * Initialize product collection
112: *
113: * @param Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection $collection
114: * @return Mage_Catalog_Model_Layer
115: */
116: public function prepareProductCollection($collection)
117: {
118: $collection
119: ->addAttributeToSelect(Mage::getSingleton('catalog/config')->getProductAttributes())
120: ->addMinimalPrice()
121: ->addFinalPrice()
122: ->addTaxPercents()
123: ->addUrlRewrite($this->getCurrentCategory()->getId());
124:
125: Mage::getSingleton('catalog/product_status')->addVisibleFilterToCollection($collection);
126: Mage::getSingleton('catalog/product_visibility')->addVisibleInCatalogFilterToCollection($collection);
127:
128: return $this;
129: }
130:
131: /**
132: * Apply layer
133: * Method is colling after apply all filters, can be used
134: * for prepare some index data before getting information
135: * about existing intexes
136: *
137: * @return Mage_Catalog_Model_Layer
138: */
139: public function apply()
140: {
141: $stateSuffix = '';
142: foreach ($this->getState()->getFilters() as $filterItem) {
143: $stateSuffix .= '_' . $filterItem->getFilter()->getRequestVar()
144: . '_' . $filterItem->getValueString();
145: }
146: if (!empty($stateSuffix)) {
147: $this->_stateKey = $this->getStateKey().$stateSuffix;
148: }
149:
150: return $this;
151: }
152:
153: /**
154: * Retrieve current category model
155: * If no category found in registry, the root will be taken
156: *
157: * @return Mage_Catalog_Model_Category
158: */
159: public function getCurrentCategory()
160: {
161: $category = $this->getData('current_category');
162: if (is_null($category)) {
163: if ($category = Mage::registry('current_category')) {
164: $this->setData('current_category', $category);
165: }
166: else {
167: $category = Mage::getModel('catalog/category')->load($this->getCurrentStore()->getRootCategoryId());
168: $this->setData('current_category', $category);
169: }
170: }
171:
172: return $category;
173: }
174:
175: /**
176: * Change current category object
177: *
178: * @param mixed $category
179: * @return Mage_Catalog_Model_Layer
180: */
181: public function setCurrentCategory($category)
182: {
183: if (is_numeric($category)) {
184: $category = Mage::getModel('catalog/category')->load($category);
185: }
186: if (!$category instanceof Mage_Catalog_Model_Category) {
187: Mage::throwException(Mage::helper('catalog')->__('Category must be an instance of Mage_Catalog_Model_Category.'));
188: }
189: if (!$category->getId()) {
190: Mage::throwException(Mage::helper('catalog')->__('Invalid category.'));
191: }
192:
193: if ($category->getId() != $this->getCurrentCategory()->getId()) {
194: $this->setData('current_category', $category);
195: }
196:
197: return $this;
198: }
199:
200: /**
201: * Retrieve current store model
202: *
203: * @return Mage_Core_Model_Store
204: */
205: public function getCurrentStore()
206: {
207: return Mage::app()->getStore();
208: }
209:
210: /**
211: * Get collection of all filterable attributes for layer products set
212: *
213: * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Attribute_Collection
214: */
215: public function getFilterableAttributes()
216: {
217: // $entity = Mage::getSingleton('eav/config')
218: // ->getEntityType('catalog_product');
219:
220: $setIds = $this->_getSetIds();
221: if (!$setIds) {
222: return array();
223: }
224: /** @var $collection Mage_Catalog_Model_Resource_Product_Attribute_Collection */
225: $collection = Mage::getResourceModel('catalog/product_attribute_collection');
226: $collection
227: ->setItemObjectClass('catalog/resource_eav_attribute')
228: ->setAttributeSetFilter($setIds)
229: ->addStoreLabel(Mage::app()->getStore()->getId())
230: ->setOrder('position', 'ASC');
231: $collection = $this->_prepareAttributeCollection($collection);
232: $collection->load();
233:
234: return $collection;
235: }
236:
237: /**
238: * Prepare attribute for use in layered navigation
239: *
240: * @param Mage_Eav_Model_Entity_Attribute $attribute
241: * @return Mage_Eav_Model_Entity_Attribute
242: */
243: protected function _prepareAttribute($attribute)
244: {
245: Mage::getResourceSingleton('catalog/product')->getAttribute($attribute);
246: return $attribute;
247: }
248:
249: /**
250: * Add filters to attribute collection
251: *
252: * @param Mage_Catalog_Model_Resource_Eav_Mysql4_Attribute_Collection $collection
253: * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Attribute_Collection
254: */
255: protected function _prepareAttributeCollection($collection)
256: {
257: $collection->addIsFilterableFilter();
258: return $collection;
259: }
260:
261: /**
262: * Retrieve layer state object
263: *
264: * @return Mage_Catalog_Model_Layer_State
265: */
266: public function getState()
267: {
268: $state = $this->getData('state');
269: if (is_null($state)) {
270: Varien_Profiler::start(__METHOD__);
271: $state = Mage::getModel('catalog/layer_state');
272: $this->setData('state', $state);
273: Varien_Profiler::stop(__METHOD__);
274: }
275:
276: return $state;
277: }
278:
279: /**
280: * Get attribute sets identifiers of current product set
281: *
282: * @return array
283: */
284: protected function _getSetIds()
285: {
286: $key = $this->getStateKey().'_SET_IDS';
287: $setIds = $this->getAggregator()->getCacheData($key);
288:
289: if ($setIds === null) {
290: $setIds = $this->getProductCollection()->getSetIds();
291: $this->getAggregator()->saveCacheData($setIds, $key, $this->getStateTags());
292: }
293:
294: return $setIds;
295: }
296: }
297: