1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25:
26:
27:
28: 29: 30: 31: 32: 33: 34:
35: class Mage_Bundle_Model_Resource_Price_Index extends Mage_Core_Model_Resource_Db_Abstract
36: {
37: 38: 39: 40: 41:
42: protected $_attributes = array();
43:
44: 45: 46: 47: 48:
49: protected $_websites;
50:
51: 52: 53: 54: 55:
56: protected $_customerGroups;
57:
58: 59: 60: 61:
62: protected function _construct()
63: {
64: $this->_init('bundle/price_index', 'entity_id');
65: }
66:
67: 68: 69: 70: 71: 72:
73: protected function _getAttribute($attributeCode)
74: {
75: if (!isset($this->_attributes[$attributeCode])) {
76: $this->_attributes[$attributeCode] = Mage::getSingleton('catalog/config')
77: ->getAttribute(Mage_Catalog_Model_Product::ENTITY, $attributeCode);
78: }
79: return $this->_attributes[$attributeCode];
80: }
81:
82: 83: 84: 85: 86:
87: protected function _getWebsites()
88: {
89: if (is_null($this->_websites)) {
90: $this->_websites = Mage::app()->getWebsites(false);
91: }
92: return $this->_websites;
93: }
94:
95: 96: 97: 98: 99:
100: protected function _getCustomerGroups()
101: {
102: if (is_null($this->_customerGroups)) {
103: $this->_customerGroups = array();
104: foreach (Mage::getModel('customer/group')->getCollection() as $group) {
105: $this->_customerGroups[$group->getId()] = $group;
106: }
107: }
108: return $this->_customerGroups;
109: }
110:
111: 112: 113: 114: 115: 116: 117: 118:
119: public function getProducts($product = null, $lastEntityId = 0, $limit = 100)
120: {
121:
122: $select = $this->_getReadAdapter()->select()
123: ->from(
124: array('e' => $this->getTable('catalog/product')),
125: array('entity_id')
126: )
127: ->where('e.type_id=?', Mage_Catalog_Model_Product_Type::TYPE_BUNDLE);
128: if ($product instanceof Mage_Catalog_Model_Product) {
129: $select->where('e.entity_id=?', $product->getId());
130: } elseif ($product instanceof Mage_Catalog_Model_Product_Condition_Interface) {
131: $value = new Zend_Db_Expr($product->getIdsSelect($this->_getReadAdapter()));
132: $select->where('e.entity_id IN(?)', $value);
133: } elseif (is_numeric($product) || is_array($product)) {
134: $select->where('e.entity_id IN(?)', $product);
135: }
136:
137: $priceType = $this->_getAttribute('price_type');
138: $priceTypeAlias = 't_' . $priceType->getAttributeCode();
139: $joinConds = array(
140: $priceTypeAlias . '.attribute_id=:attribute_id',
141: $priceTypeAlias . '.store_id=0',
142: $priceTypeAlias . '.entity_id=e.entity_id'
143: );
144:
145: $select->joinLeft(
146: array($priceTypeAlias => $priceType->getBackend()->getTable()),
147: join(' AND ', $joinConds),
148: array('price_type' => $priceTypeAlias . '.value')
149: );
150:
151: $select->where('e.entity_id>:last_entity_id', $lastEntityId)
152: ->order('e.entity_id')
153: ->limit($limit);
154: $bind = array(
155: 'attribute_id' => $priceType->getAttributeId(),
156: 'last_entity_id' => $lastEntityId
157: );
158: return $this->_getReadAdapter()->fetchPairs($select, $bind);
159: }
160:
161: 162: 163: 164: 165: 166:
167: public function reindex($products = null)
168: {
169: $lastEntityId = 0;
170: while (true) {
171: $productsData = $this->getProducts($products, $lastEntityId);
172: if (!$productsData) {
173: break;
174: }
175:
176: foreach ($productsData as $productId => $priceType) {
177: $this->_reindexProduct($productId, $priceType);
178: $lastEntityId = $productId;
179: }
180: }
181:
182: return $this;
183: }
184:
185: 186: 187: 188: 189: 190: 191:
192: protected function _reindexProduct($productId, $priceType)
193: {
194: $options = $this->getSelections($productId);
195: $selectionProducts = array();
196: foreach ($options as $option) {
197: foreach ($option['selections'] as $selection) {
198: $selectionProducts[$selection['product_id']] = $selection['product_id'];
199: }
200: }
201:
202: $priceIndex = array();
203: if ($priceType == Mage_Bundle_Model_Product_Price::PRICE_TYPE_DYNAMIC) {
204:
205: $priceIndex = $this->getProductsPriceFromIndex($selectionProducts);
206: }
207:
208: foreach ($this->_getWebsites() as $website) {
209: if (!$website->getDefaultStore()) {
210: continue;
211: }
212: $salableStatus = $this->getProductsSalableStatus($selectionProducts, $website);
213: $priceData = $this->getProductsPriceData($productId, $website);
214: $priceData = $priceData[$productId];
215:
216:
217: foreach ($this->_getCustomerGroups() as $group) {
218:
219: if ($priceType == Mage_Bundle_Model_Product_Price::PRICE_TYPE_FIXED) {
220: $basePrice = $this->_getBasePrice($productId, $priceData, $website, $group);
221: $customOptions = $this->getCustomOptions($productId, $website);
222: } elseif ($priceType == Mage_Bundle_Model_Product_Price::PRICE_TYPE_DYNAMIC) {
223: $basePrice = 0;
224: }
225:
226: list($minPrice, $maxPrice) = $this->_calculateBundleSelections($options, $salableStatus,
227: $productId, $priceType, $basePrice, $priceData, $priceIndex, $website, $group
228: );
229:
230: if ($priceType == Mage_Bundle_Model_Product_Price::PRICE_TYPE_FIXED) {
231: list($minPrice, $maxPrice) =
232: $this->_calculateCustomOptions($customOptions, $basePrice, $minPrice, $maxPrice);
233: }
234:
235: $this->_savePriceIndex($productId, $website->getId(), $group->getId(), $minPrice, $maxPrice);
236: }
237: }
238:
239: return $this;
240: }
241:
242: 243: 244: 245: 246: 247: 248: 249: 250: 251:
252: protected function _savePriceIndex($productId, $websiteId, $groupId, $minPrice, $maxPrice)
253: {
254: $adapter = $this->_getWriteAdapter();
255: $adapter->beginTransaction();
256: $bind = array($productId, $websiteId, $groupId, $minPrice, $maxPrice);
257: $adapter->insertOnDuplicate($this->getMainTable(), $bind, array('min_price', 'max_price'));
258: $adapter->commit();
259:
260: return $this;
261: }
262:
263: 264: 265: 266: 267: 268:
269: public function getSelections($productId)
270: {
271: $options = array();
272: $read = $this->_getReadAdapter();
273: $select = $read->select()
274: ->from(
275: array('option_table' => $this->getTable('bundle/option')),
276: array('option_id', 'required', 'type')
277: )
278: ->join(
279: array('selection_table' => $this->getTable('bundle/selection')),
280: 'selection_table.option_id=option_table.option_id',
281: array('selection_id', 'product_id', 'selection_price_type',
282: 'selection_price_value', 'selection_qty', 'selection_can_change_qty')
283: )
284: ->join(
285: array('e' => $this->getTable('catalog/product')),
286: 'e.entity_id=selection_table.product_id AND e.required_options=0',
287: array()
288: )
289: ->where('option_table.parent_id=:product_id');
290:
291: $query = $read->query($select, array('product_id' => $productId));
292: while ($row = $query->fetch()) {
293: if (!isset($options[$row['option_id']])) {
294: $options[$row['option_id']] = array(
295: 'option_id' => $row['option_id'],
296: 'required' => $row['required'],
297: 'type' => $row['type'],
298: 'selections' => array()
299: );
300: }
301: $options[$row['option_id']]['selections'][$row['selection_id']] = array(
302: 'selection_id' => $row['selection_id'],
303: 'product_id' => $row['product_id'],
304: 'price_type' => $row['selection_price_type'],
305: 'price_value' => $row['selection_price_value'],
306: 'qty' => $row['selection_qty'],
307: 'can_change_qty' => $row['selection_can_change_qty']
308: );
309: }
310:
311: return $options;
312: }
313:
314: 315: 316: 317: 318: 319: 320:
321: public function getProductsSalableStatus($products, Mage_Core_Model_Website $website)
322: {
323: $read = $this->_getReadAdapter();
324: $productsData = array();
325: $select = $read->select()
326: ->from(array('e' => $this->getTable('catalog/product')), 'entity_id')
327: ->where('e.entity_id IN(?)', $products);
328:
329: $select->joinLeft(
330: array('pw' => $this->getTable('catalog/product_website')),
331: 'e.entity_id=pw.product_id AND pw.website_id=:website_id',
332: array('pw.website_id')
333: );
334:
335: $store = $website->getDefaultStore();
336:
337:
338: $status = $this->_getAttribute('status');
339: if ($status->isScopeGlobal()) {
340: $select->join(
341: array('t_status' => $status->getBackend()->getTable()),
342: 'e.entity_id=t_status.entity_id'
343: . ' AND t_status.attribute_id=:status_attribute_id'
344: . ' AND t_status.store_id=0',
345: array('status' => 't_status.value')
346: );
347: } else {
348:
349: $statusField = $read->getCheckSql(
350: 't2_status.value_id > 0',
351: 't2_status.value',
352: 't1_status.value'
353: );
354:
355: $statusTable = $status->getBackend()->getTable();
356: $select->join(
357: array('t1_status' => $statusTable),
358: 'e.entity_id=t1_status.entity_id'
359: . ' AND t1_status.attribute_id=:status_attribute_id'
360: . ' AND t1_status.store_id=0',
361: array('status' => $statusField)
362: )
363: ->joinLeft(
364: array('t2_status' => $statusTable),
365: 't1_status.entity_id = t2_status.entity_id'
366: . ' AND t1_status.attribute_id = t2_status.attribute_id'
367: . ' AND t2_status.store_id=:store_id',
368: array()
369: );
370: }
371:
372: $bind = array(
373: 'status_attribute_id' => $status->getAttributeId(),
374: 'website_id' => $website->getId(),
375: 'store_id' => $store->getId()
376: );
377:
378: Mage::dispatchEvent('catalog_product_prepare_index_select', array(
379: 'website' => $website,
380: 'select' => $select,
381: 'bind' => $bind
382: ));
383:
384: $query = $read->query($select, $bind);
385: while ($row = $query->fetch()) {
386: $salable = isset($row['salable']) ? $row['salable'] : true;
387: $website = $row['website_id'] > 0 ? true : false;
388: $status = $row['status'];
389:
390: $productsData[$row['entity_id']] = $salable && $status && $website;
391: }
392:
393: return $productsData;
394: }
395:
396: 397: 398: 399: 400: 401: 402:
403: public function getProductsPriceFromIndex($productIds)
404: {
405: $price = $this->_getAttribute('price');
406: $read = $this->_getReadAdapter();
407: $key = $read->getConcatSql(array('entity_id', 'customer_group_id', 'website_id'), '-');
408:
409: $select = $read->select()
410: ->from(
411: array('price_index' => $this->getTable('catalogindex/price')),
412: array('index_key' => $key, 'value')
413: )
414: ->where('entity_id IN(?)', $productIds)
415: ->where('attribute_id= :attribute_id');
416: $index = $read->fetchPairs($select, array('attribute_id' => $price->getAttributeId()));
417: return $index;
418: }
419:
420: 421: 422: 423: 424: 425: 426:
427: public function getProductsPriceData($products, Mage_Core_Model_Website $website)
428: {
429: $productsData = array();
430: $read = $this->_getReadAdapter();
431: $select = $read->select()
432: ->from(array('e' => $this->getTable('catalog/product')), 'entity_id')
433: ->where('e.entity_id IN(?)', $products);
434:
435: $this->_addAttributeDataToSelect($select, 'price', $website);
436: $this->_addAttributeDataToSelect($select, 'special_price', $website);
437: $this->_addAttributeDataToSelect($select, 'special_from_date', $website);
438: $this->_addAttributeDataToSelect($select, 'special_to_date', $website);
439:
440: $query = $read->query($select);
441: while ($row = $query->fetch()) {
442: $productsData[$row['entity_id']] = array(
443: 'price' => $row['price'],
444: 'special_price' => $row['special_price'],
445: 'special_from_date' => $row['special_from_date'],
446: 'special_to_date' => $row['special_to_date']
447: );
448: }
449:
450: return $productsData;
451: }
452:
453: 454: 455: 456: 457: 458: 459: 460:
461: protected function _addAttributeDataToSelect(Varien_Db_Select $select, $attributeCode,
462: Mage_Core_Model_Website $website)
463: {
464: $attribute = $this->_getAttribute($attributeCode);
465: $store = $website->getDefaultStore();
466: if ($attribute->isScopeGlobal()) {
467: $table = 't_' . $attribute->getAttributeCode();
468: $select->joinLeft(
469: array($table => $attribute->getBackend()->getTable()),
470: "e.entity_id={$table}.entity_id"
471: . " AND {$table}.attribute_id={$attribute->getAttributeId()}"
472: . " AND {$table}.store_id=0",
473: array($attribute->getAttributeCode() => $table . '.value')
474: );
475: } else {
476: $tableName = $attribute->getBackend()->getTable();
477: $tableGlobal = 't1_' . $attribute->getAttributeCode();
478: $tableStore = 't2_' . $attribute->getAttributeCode();
479:
480: $attributeCond = $this->getReadConnection()->getCheckSql(
481: $tableStore . '.value_id > 0',
482: $tableStore . '.value',
483: $tableGlobal . '.value'
484: );
485: $select->joinLeft(
486: array($tableGlobal => $tableName),
487: "e.entity_id = {$tableGlobal}.entity_id"
488: . " AND {$tableGlobal}.attribute_id = {$attribute->getAttributeId()}"
489: . " AND {$tableGlobal}.store_id = 0",
490: array($attribute->getAttributeCode() => $attributeCond)
491: )
492: ->joinLeft(
493: array($tableStore => $tableName),
494: "{$tableGlobal}.entity_id = {$tableStore}.entity_id"
495: . " AND {$tableGlobal}.attribute_id = {$tableStore}.attribute_id"
496: . " AND {$tableStore}.store_id = " . $store->getId(),
497: array()
498: );
499: }
500: return $this;
501: }
502:
503: 504: 505: 506: 507: 508: 509: 510: 511:
512: protected function _getBasePrice($productId, array $priceData, $website, $customerGroup)
513: {
514: $store = $website->getDefaultStore();
515: $storeTimeStamp = Mage::app()->getLocale()->storeTimeStamp($store);
516: $finalPrice = $this->_calculateSpecialPrice($priceData['price'], $priceData, $website);
517:
518: $rulePrice = Mage::getResourceModel('catalogrule/rule')
519: ->getRulePrice($storeTimeStamp, $website->getId(), $customerGroup->getId(), $productId);
520:
521: if ($rulePrice !== null && $rulePrice !== false) {
522: $finalPrice = min($finalPrice, $rulePrice);
523: }
524:
525: return $finalPrice;
526: }
527:
528: 529: 530: 531: 532: 533: 534:
535: public function getCustomOptions($productId, Mage_Core_Model_Website $website)
536: {
537: $options = array();
538: $store = $website->getDefaultStore();
539: $price = $this->_getAttribute('price');
540: $adapter = $this->_getReadAdapter();
541:
542: $bind = array(
543: ':product_id' => $productId,
544: ':store_id' => $store->getId(),
545:
546: );
547: $select = $adapter->select()
548: ->from(
549: array('option_table' => $this->getTable('catalog/product_option')),
550: array('option_id', 'is_require', 'type')
551: )
552: ->where('option_table.product_id=:product_id');
553:
554: if ($price->isScopeGlobal()) {
555: $select->join(
556: array('price_table' => $this->getTable('catalog/product_option_price')),
557: 'option_table.option_id = price_table.option_id' .
558: ' AND price_table.store_id = 0',
559: array('value_id' => 'option_price_id', 'price', 'price_type')
560: );
561: } else {
562: $valueIdCond = $adapter->getCheckSql(
563: 'price_store_table.option_price_id IS NOT NULL',
564: 'price_store_table.option_price_id',
565: 'price_global_table.option_price_id'
566: );
567: $priceCond = $adapter->getCheckSql(
568: 'price_store_table.price IS NOT NULL',
569: 'price_store_table.price',
570: 'price_global_table.price'
571: );
572: $priceTypeCond = $adapter->getCheckSql(
573: 'price_store_table.price_type IS NOT NULL',
574: 'price_store_table.price_type',
575: 'price_global_table.price_type'
576: );
577:
578: $select
579: ->join(
580: array('price_global_table' => $this->getTable('catalog/product_option_price')),
581: 'option_table.option_id=price_global_table.option_id' .
582: ' AND price_global_table.store_id=0',
583: array(
584: 'value_id' => $valueIdCond,
585: 'price' => $priceCond,
586: 'price_type' => $priceTypeCond
587: ))
588: ->joinLeft(
589: array('price_store_table' => $this->getTable('catalog/product_option_price')),
590: 'option_table.option_id = price_store_table.option_id' .
591: ' AND price_store_table.store_id=:store_id',
592: array()
593: );
594: }
595:
596: $query = $adapter->query($select, $bind);
597: while ($row = $query->fetch()) {
598: if (!isset($options[$row['option_id']])) {
599: $options[$row['option_id']] = array(
600: 'option_id' => $row['option_id'],
601: 'is_require' => $row['is_require'],
602: 'type' => $row['type'],
603: 'values' => array()
604: );
605: }
606: $options[$row['option_id']]['values'][$row['value_id']] = array(
607: 'price_type' => $row['price_type'],
608: 'price_value' => $row['price']
609: );
610: }
611:
612: $select = $adapter->select()
613: ->from(
614: array('option_table' => $this->getTable('catalog/product_option')),
615: array('option_id', 'is_require', 'type')
616: )
617: ->join(
618: array('type_table' => $this->getTable('catalog/product_option_type_value')),
619: 'option_table.option_id=type_table.option_id',
620: array()
621: )
622: ->where('option_table.product_id=:product_id');
623:
624: if ($price->isScopeGlobal()) {
625: $select->join(
626: array('price_table' => $this->getTable('catalog/product_option_type_price')),
627: 'type_table.option_type_id=price_table.option_type_id' .
628: ' AND price_table.store_id=0',
629: array('value_id' => 'option_type_id', 'price', 'price_type')
630: );
631: } else {
632: $select
633: ->join(
634: array('price_global_table' => $this->getTable('catalog/product_option_type_price')),
635: 'type_table.option_type_id=price_global_table.option_type_id' .
636: ' AND price_global_table.store_id=0',
637: array(
638: 'value_id' => $valueIdCond,
639: 'price' => $priceCond,
640: 'price_type' => $priceTypeCond
641: )
642: )
643: ->joinLeft(
644: array('price_store_table' => $this->getTable('catalog/product_option_type_price')),
645: 'type_table.option_type_id=price_store_table.option_type_id' .
646: ' AND price_store_table.store_id=:store_id',
647: array()
648: );
649: }
650:
651: $query = $adapter->query($select, $bind);
652: while ($row = $query->fetch()) {
653: if (!isset($options[$row['option_id']])) {
654: $options[$row['option_id']] = array(
655: 'option_id' => $row['option_id'],
656: 'is_require' => $row['is_require'],
657: 'type' => $row['type'],
658: 'values' => array()
659: );
660: }
661: $options[$row['option_id']]['values'][$row['value_id']] = array(
662: 'price_type' => $row['price_type'],
663: 'price_value' => $row['price']
664: );
665: }
666:
667: return $options;
668: }
669:
670: 671: 672: 673: 674: 675: 676: 677: 678: 679:
680: public function _calculateCustomOptions(array $options, $basePrice, $minPrice, $maxPrice)
681: {
682: foreach ($options as $option) {
683: $optionPrices = array();
684: foreach ($option['values'] as $value) {
685: if ($value['price_type'] == 'percent') {
686: $valuePrice = $basePrice * $value['price_value'] / 100;
687: } else {
688: $valuePrice = $value['price_value'];
689: }
690: $optionPrices[] = $valuePrice;
691: }
692: if ($option['is_require']) {
693: $minPrice += min($optionPrices);
694: }
695: $multiTypes = array(
696: Mage_Catalog_Model_Product_Option::OPTION_TYPE_DROP_DOWN,
697: Mage_Catalog_Model_Product_Option::OPTION_TYPE_CHECKBOX,
698: Mage_Catalog_Model_Product_Option::OPTION_TYPE_MULTIPLE
699: );
700: if ($optionPrices) {
701: if (in_array($option['type'], $multiTypes)) {
702: $maxPrice += array_sum($optionPrices);
703: } else {
704: $maxPrice += max($optionPrices);
705: }
706: }
707: }
708:
709: return array($minPrice, $maxPrice);
710: }
711:
712: 713: 714: 715: 716: 717: 718: 719: 720: 721: 722: 723: 724: 725: 726:
727: public function _calculateBundleSelections(array $options, array $salableStatus, $productId, $priceType, $basePrice,
728: $priceData, $priceIndex, $website, $group)
729: {
730: $minPrice = $maxPrice = $basePrice;
731: $optPrice = 0;
732:
733: foreach ($options as $option) {
734: $optionPrices = array();
735: foreach ($option['selections'] as $selection) {
736: if (!$selection['product_id']) {
737: continue;
738: }
739:
740: if (!$salableStatus[$selection['product_id']]) {
741: continue;
742: }
743:
744: if ($priceType == Mage_Bundle_Model_Product_Price::PRICE_TYPE_FIXED) {
745: $basePrice = $this->_getBasePrice($productId, $priceData, $website, $group);
746: }
747:
748:
749: if ($priceType == Mage_Bundle_Model_Product_Price::PRICE_TYPE_DYNAMIC) {
750: $priceIndexKey = join('-', array(
751: $selection['product_id'],
752: $website->getId(),
753: $group->getId()
754: ));
755:
756: $selectionPrice = isset($priceIndex[$priceIndexKey]) ? $priceIndex[$priceIndexKey] : 0;
757: $selectionPrice = $this->_calculateSpecialPrice($selectionPrice, $priceData, $website);
758: } else {
759: if ($selection['price_type']) {
760: $selectionPrice = $basePrice * $selection['price_value'] / 100;
761: } else {
762: $selectionPrice = $this->_calculateSpecialPrice($selection['price_value'],
763: $priceData, $website);
764: }
765: }
766:
767:
768: if ($selection['can_change_qty'] && $option['type'] != 'multi' && $option['type'] != 'checkbox') {
769: $qty = 1;
770: } else {
771: $qty = $selection['qty'];
772: }
773:
774: $selectionPrice = $selectionPrice * $qty;
775: $optionPrices[$selection['selection_id']] = $selectionPrice;
776: }
777:
778: if ($optionPrices) {
779: if ($option['required']) {
780: $minPrice += min($optionPrices);
781: } else {
782: $optPrice = $optPrice && $optPrice < min($optionPrices) ? $optPrice : min($optionPrices);
783: }
784: if (in_array($option['type'], array('multi', 'checkbox'))) {
785: $maxPrice += array_sum($optionPrices);
786: } else {
787: $maxPrice += max($optionPrices);
788: }
789: }
790: }
791:
792: if ($minPrice == 0) {
793: $minPrice = $optPrice;
794: }
795: return array($minPrice, $maxPrice);
796: }
797:
798: 799: 800: 801: 802: 803: 804: 805:
806: public function _calculateSpecialPrice($finalPrice, array $priceData, Mage_Core_Model_Website $website)
807: {
808: $store = $website->getDefaultStore();
809: $specialPrice = $priceData['special_price'];
810:
811: if (!is_null($specialPrice) && $specialPrice != false) {
812: if (Mage::app()->getLocale()->isStoreDateInInterval($store, $priceData['special_from_date'],
813: $priceData['special_to_date'])) {
814: $specialPrice = ($finalPrice * $specialPrice) / 100;
815: $finalPrice = min($finalPrice, $specialPrice);
816: }
817: }
818:
819: return $finalPrice;
820: }
821:
822: 823: 824: 825: 826: 827: 828: 829:
830: public function loadPriceIndex($productIds, $websiteId, $groupId)
831: {
832: $prices = array();
833: $adapter = $this->_getReadAdapter();
834: $select = $adapter->select()
835: ->from(
836: array('pi' => $this->getMainTable()),
837: array('entity_id', 'min_price', 'max_price')
838: )
839: ->where('entity_id IN(?)', $productIds)
840: ->where('website_id=:website_id')
841: ->where('customer_group_id=:group_id');
842: $bind = array(
843: 'website_id' => $websiteId,
844: 'group_id' => $groupId
845: );
846: $query = $adapter->query($select, $bind);
847: while ($row = $query->fetch()) {
848: $prices[$row['entity_id']] = array(
849: 'min_price' => $row['min_price'],
850: 'max_price' => $row['max_price']
851: );
852: }
853:
854: return $prices;
855: }
856: }
857: