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: class Mage_Bundle_Model_Product_Type extends Mage_Catalog_Model_Product_Type_Abstract
35: {
36: 37: 38: 39: 40:
41: protected $_isComposite = true;
42:
43: 44: 45: 46: 47:
48: protected $_keyOptionsCollection = '_cache_instance_options_collection';
49:
50: 51: 52: 53: 54:
55: protected $_keySelectionsCollection = '_cache_instance_selections_collection';
56:
57: 58: 59: 60: 61:
62: protected $_keyUsedSelections = '_cache_instance_used_selections';
63:
64: 65: 66: 67: 68:
69: protected $_keyUsedSelectionsIds = '_cache_instance_used_selections_ids';
70:
71: 72: 73: 74: 75:
76: protected $_keyUsedOptions = '_cache_instance_used_options';
77:
78: 79: 80: 81: 82:
83: protected $_keyUsedOptionsIds = '_cache_instance_used_options_ids';
84:
85: 86: 87: 88: 89:
90: protected $_canConfigure = true;
91:
92: 93: 94: 95: 96:
97: public function getRelationInfo()
98: {
99: $info = new Varien_Object();
100: $info->setTable('bundle/selection')
101: ->setParentFieldName('parent_product_id')
102: ->setChildFieldName('product_id');
103: return $info;
104: }
105:
106: 107: 108: 109: 110: 111: 112: 113: 114: 115:
116: public function getChildrenIds($parentId, $required = true)
117: {
118: return Mage::getResourceSingleton('bundle/selection')
119: ->getChildrenIds($parentId, $required);
120: }
121:
122: 123: 124: 125: 126: 127:
128: public function getParentIdsByChild($childId)
129: {
130: return Mage::getResourceSingleton('bundle/selection')
131: ->getParentIdsByChild($childId);
132: }
133:
134: 135: 136: 137: 138: 139:
140: public function getSku($product = null)
141: {
142: $sku = parent::getSku($product);
143:
144: if ($this->getProduct($product)->getData('sku_type')) {
145: return $sku;
146: } else {
147: $skuParts = array($sku);
148:
149: if ($this->getProduct($product)->hasCustomOptions()) {
150: $customOption = $this->getProduct($product)->getCustomOption('bundle_selection_ids');
151: $selectionIds = unserialize($customOption->getValue());
152: if (!empty($selectionIds)) {
153: $selections = $this->getSelectionsByIds($selectionIds, $product);
154: foreach ($selections->getItems() as $selection) {
155: $skuParts[] = $selection->getSku();
156: }
157: }
158: }
159:
160: return implode('-', $skuParts);
161: }
162: }
163:
164: 165: 166: 167: 168: 169:
170: public function getWeight($product = null)
171: {
172: if ($this->getProduct($product)->getData('weight_type')) {
173: return $this->getProduct($product)->getData('weight');
174: } else {
175: $weight = 0;
176:
177: if ($this->getProduct($product)->hasCustomOptions()) {
178: $customOption = $this->getProduct($product)->getCustomOption('bundle_selection_ids');
179: $selectionIds = unserialize($customOption->getValue());
180: $selections = $this->getSelectionsByIds($selectionIds, $product);
181: foreach ($selections->getItems() as $selection) {
182: $qtyOption = $this->getProduct($product)
183: ->getCustomOption('selection_qty_' . $selection->getSelectionId());
184: if ($qtyOption) {
185: $weight += $selection->getWeight() * $qtyOption->getValue();
186: } else {
187: $weight += $selection->getWeight();
188: }
189: }
190: }
191: return $weight;
192: }
193: }
194:
195: 196: 197: 198: 199: 200:
201: public function isVirtual($product = null)
202: {
203: if ($this->getProduct($product)->hasCustomOptions()) {
204: $customOption = $this->getProduct($product)->getCustomOption('bundle_selection_ids');
205: $selectionIds = unserialize($customOption->getValue());
206: $selections = $this->getSelectionsByIds($selectionIds, $product);
207: $virtualCount = 0;
208: foreach ($selections->getItems() as $selection) {
209: if ($selection->isVirtual()) {
210: $virtualCount++;
211: }
212: }
213: if ($virtualCount == count($selections)) {
214: return true;
215: }
216: }
217: return false;
218: }
219:
220: 221: 222: 223: 224:
225: public function beforeSave($product = null)
226: {
227: parent::beforeSave($product);
228: $product = $this->getProduct($product);
229:
230:
231: if (!$product->getData('weight_type') && $product->hasData('weight')) {
232: $product->setData('weight', false);
233: }
234:
235: if ($product->getPriceType() == Mage_Bundle_Model_Product_Price::PRICE_TYPE_DYNAMIC) {
236: $product->setData(
237: 'msrp_enabled', Mage_Catalog_Model_Product_Attribute_Source_Msrp_Type_Enabled::MSRP_ENABLE_NO
238: );
239: $product->unsetData('msrp');
240: $product->unsetData('msrp_display_actual_price_type');
241: }
242:
243: $product->canAffectOptions(false);
244:
245: if ($product->getCanSaveBundleSelections()) {
246: $product->canAffectOptions(true);
247: $selections = $product->getBundleSelectionsData();
248: if ($selections) {
249: if (!empty($selections)) {
250: $options = $product->getBundleOptionsData();
251: if ($options) {
252: foreach ($options as $option) {
253: if (empty($option['delete']) || 1 != (int)$option['delete']) {
254: $product->setTypeHasOptions(true);
255: if (1 == (int)$option['required']) {
256: $product->setTypeHasRequiredOptions(true);
257: break;
258: }
259: }
260: }
261: }
262: }
263: }
264: }
265: }
266:
267: 268: 269: 270: 271: 272:
273: public function save($product = null)
274: {
275: parent::save($product);
276: $product = $this->getProduct($product);
277:
278: $resource = Mage::getResourceModel('bundle/bundle');
279:
280: $options = $product->getBundleOptionsData();
281: if ($options) {
282: $product->setIsRelationsChanged(true);
283:
284: foreach ($options as $key => $option) {
285: if (isset($option['option_id']) && $option['option_id'] == '') {
286: unset($option['option_id']);
287: }
288:
289: $optionModel = Mage::getModel('bundle/option')
290: ->setData($option)
291: ->setParentId($product->getId())
292: ->setStoreId($product->getStoreId());
293:
294: $optionModel->isDeleted((bool)$option['delete']);
295: $optionModel->save();
296:
297: $options[$key]['option_id'] = $optionModel->getOptionId();
298: }
299:
300: $usedProductIds = array();
301: $excludeSelectionIds = array();
302:
303: $selections = $product->getBundleSelectionsData();
304: if ($selections) {
305: foreach ($selections as $index => $group) {
306: foreach ($group as $key => $selection) {
307: if (isset($selection['selection_id']) && $selection['selection_id'] == '') {
308: unset($selection['selection_id']);
309: }
310:
311: if (!isset($selection['is_default'])) {
312: $selection['is_default'] = 0;
313: }
314:
315: $selectionModel = Mage::getModel('bundle/selection')
316: ->setData($selection)
317: ->setOptionId($options[$index]['option_id'])
318: ->setParentProductId($product->getId());
319:
320: $selectionModel->isDeleted((bool)$selection['delete']);
321: $selectionModel->save();
322:
323: $selection['selection_id'] = $selectionModel->getSelectionId();
324:
325: if ($selectionModel->getSelectionId()) {
326: $excludeSelectionIds[] = $selectionModel->getSelectionId();
327: $usedProductIds[] = $selectionModel->getProductId();
328: }
329: }
330: }
331:
332: $resource->dropAllUnneededSelections($product->getId(), $excludeSelectionIds);
333: $resource->saveProductRelations($product->getId(), array_unique($usedProductIds));
334: }
335:
336: if ($product->getData('price_type') != $product->getOrigData('price_type')) {
337: $resource->dropAllQuoteChildItems($product->getId());
338: }
339: }
340:
341: return $this;
342: }
343:
344: 345: 346: 347: 348: 349:
350: public function getOptions($product = null)
351: {
352: return $this->getOptionsCollection($product)->getItems();
353: }
354:
355: 356: 357: 358: 359: 360:
361: public function getOptionsIds($product = null)
362: {
363: return $this->getOptionsCollection($product)->getAllIds();
364: }
365:
366: 367: 368: 369: 370: 371:
372: public function getOptionsCollection($product = null)
373: {
374: if (!$this->getProduct($product)->hasData($this->_keyOptionsCollection)) {
375: $optionsCollection = Mage::getModel('bundle/option')->getResourceCollection()
376: ->setProductIdFilter($this->getProduct($product)->getId())
377: ->setPositionOrder();
378:
379: $storeId = $this->getStoreFilter($product);
380: if ($storeId instanceof Mage_Core_Model_Store) {
381: $storeId = $storeId->getId();
382: }
383:
384: $optionsCollection->joinValues($storeId);
385: $this->getProduct($product)->setData($this->_keyOptionsCollection, $optionsCollection);
386: }
387: return $this->getProduct($product)->getData($this->_keyOptionsCollection);
388: }
389:
390: 391: 392: 393: 394: 395: 396:
397: public function getSelectionsCollection($optionIds, $product = null)
398: {
399: $keyOptionIds = (is_array($optionIds) ? implode('_', $optionIds) : '');
400: $key = $this->_keySelectionsCollection . $keyOptionIds;
401: if (!$this->getProduct($product)->hasData($key)) {
402: $storeId = $this->getProduct($product)->getStoreId();
403: $selectionsCollection = Mage::getResourceModel('bundle/selection_collection')
404: ->addAttributeToSelect(Mage::getSingleton('catalog/config')->getProductAttributes())
405: ->addAttributeToSelect('tax_class_id')
406: ->setFlag('require_stock_items', true)
407: ->setFlag('product_children', true)
408: ->setPositionOrder()
409: ->addStoreFilter($this->getStoreFilter($product))
410: ->setStoreId($storeId)
411: ->addFilterByRequiredOptions()
412: ->setOptionIdsFilter($optionIds);
413:
414: if (!Mage::helper('catalog')->isPriceGlobal() && $storeId) {
415: $websiteId = Mage::app()->getStore($storeId)->getWebsiteId();
416: $selectionsCollection->joinPrices($websiteId);
417: }
418:
419: $this->getProduct($product)->setData($key, $selectionsCollection);
420: }
421: return $this->getProduct($product)->getData($key);
422: }
423:
424: 425: 426: 427: 428: 429: 430: 431: 432: 433: 434: 435:
436: public function updateQtyOption($options, Varien_Object $option, $value, $product = null)
437: {
438: $optionProduct = $option->getProduct($product);
439: $optionUpdateFlag = $option->getHasQtyOptionUpdate();
440: $optionCollection = $this->getOptionsCollection($product);
441:
442: $selections = $this->getSelectionsCollection($optionCollection->getAllIds(), $product);
443:
444: foreach ($selections as $selection) {
445: if ($selection->getProductId() == $optionProduct->getId()) {
446: foreach ($options as &$option) {
447: if ($option->getCode() == 'selection_qty_'.$selection->getSelectionId()) {
448: if ($optionUpdateFlag) {
449: $option->setValue(intval($option->getValue()));
450: }
451: else {
452: $option->setValue($value);
453: }
454: }
455: }
456: }
457: }
458:
459: return $this;
460: }
461:
462: 463: 464: 465: 466: 467: 468:
469: public function prepareQuoteItemQty($qty, $product = null)
470: {
471: return intval($qty);
472: }
473:
474: 475: 476: 477: 478: 479:
480: public function isSalable($product = null)
481: {
482: $salable = parent::isSalable($product);
483: if (!is_null($salable)) {
484: return $salable;
485: }
486:
487: $optionCollection = $this->getOptionsCollection($product);
488:
489: if (!count($optionCollection->getItems())) {
490: return false;
491: }
492:
493: $requiredOptionIds = array();
494:
495: foreach ($optionCollection->getItems() as $option) {
496: if ($option->getRequired()) {
497: $requiredOptionIds[$option->getId()] = 0;
498: }
499: }
500:
501: $selectionCollection = $this->getSelectionsCollection($optionCollection->getAllIds(), $product);
502:
503: if (!count($selectionCollection->getItems())) {
504: return false;
505: }
506: $salableSelectionCount = 0;
507: foreach ($selectionCollection as $selection) {
508: if ($selection->isSalable()) {
509: $requiredOptionIds[$selection->getOptionId()] = 1;
510: $salableSelectionCount++;
511: }
512:
513: }
514:
515: return (array_sum($requiredOptionIds) == count($requiredOptionIds) && $salableSelectionCount);
516: }
517:
518: 519: 520: 521: 522: 523: 524: 525: 526:
527: protected function _prepareProduct(Varien_Object $buyRequest, $product, $processMode)
528: {
529: $result = parent::_prepareProduct($buyRequest, $product, $processMode);
530:
531: if (is_string($result)) {
532: return $result;
533: }
534:
535: $selections = array();
536: $product = $this->getProduct($product);
537: $isStrictProcessMode = $this->_isStrictProcessMode($processMode);
538:
539: $skipSaleableCheck = Mage::helper('catalog/product')->getSkipSaleableCheck();
540: $_appendAllSelections = (bool)$product->getSkipCheckRequiredOption() || $skipSaleableCheck;
541:
542: $options = $buyRequest->getBundleOption();
543: if (is_array($options)) {
544: $options = array_filter($options, 'intval');
545: $qtys = $buyRequest->getBundleOptionQty();
546: foreach ($options as $_optionId => $_selections) {
547: if (empty($_selections)) {
548: unset($options[$_optionId]);
549: }
550: }
551: $optionIds = array_keys($options);
552:
553: if (empty($optionIds) && $isStrictProcessMode) {
554: return Mage::helper('bundle')->__('Please select options for product.');
555: }
556:
557: $product->getTypeInstance(true)->setStoreFilter($product->getStoreId(), $product);
558: $optionsCollection = $this->getOptionsCollection($product);
559: if (!$this->getProduct($product)->getSkipCheckRequiredOption() && $isStrictProcessMode) {
560: foreach ($optionsCollection->getItems() as $option) {
561: if ($option->getRequired() && !isset($options[$option->getId()])) {
562: return Mage::helper('bundle')->__('Required options are not selected.');
563: }
564: }
565: }
566: $selectionIds = array();
567:
568: foreach ($options as $optionId => $selectionId) {
569: if (!is_array($selectionId)) {
570: if ($selectionId != '') {
571: $selectionIds[] = (int)$selectionId;
572: }
573: } else {
574: foreach ($selectionId as $id) {
575: if ($id != '') {
576: $selectionIds[] = (int)$id;
577: }
578: }
579: }
580: }
581:
582: if (!empty($selectionIds)) {
583: $selections = $this->getSelectionsByIds($selectionIds, $product);
584:
585:
586: foreach ($selections->getItems() as $key => $selection) {
587: if (!$selection->isSalable() && !$skipSaleableCheck) {
588: $_option = $optionsCollection->getItemById($selection->getOptionId());
589: if (is_array($options[$_option->getId()]) && count($options[$_option->getId()]) > 1) {
590: $moreSelections = true;
591: } else {
592: $moreSelections = false;
593: }
594: if ($_option->getRequired()
595: && (!$_option->isMultiSelection() || ($_option->isMultiSelection() && !$moreSelections))
596: ) {
597: return Mage::helper('bundle')->__('Selected required options are not available.');
598: }
599: }
600: }
601:
602: $optionsCollection->appendSelections($selections, false, $_appendAllSelections);
603:
604: $selections = $selections->getItems();
605: } else {
606: $selections = array();
607: }
608: } else {
609: $product->setOptionsValidationFail(true);
610: $product->getTypeInstance(true)->setStoreFilter($product->getStoreId(), $product);
611:
612: $optionCollection = $product->getTypeInstance(true)->getOptionsCollection($product);
613:
614: $optionIds = $product->getTypeInstance(true)->getOptionsIds($product);
615: $selectionIds = array();
616:
617: $selectionCollection = $product->getTypeInstance(true)
618: ->getSelectionsCollection(
619: $optionIds,
620: $product
621: );
622:
623: $options = $optionCollection->appendSelections($selectionCollection, false, $_appendAllSelections);
624:
625: foreach ($options as $option) {
626: if ($option->getRequired() && count($option->getSelections()) == 1) {
627: $selections = array_merge($selections, $option->getSelections());
628: } else {
629: $selections = array();
630: break;
631: }
632: }
633: }
634: if (count($selections) > 0 || !$isStrictProcessMode) {
635: $uniqueKey = array($product->getId());
636: $selectionIds = array();
637:
638:
639: usort($selections, array($this, 'shakeSelections'));
640:
641: foreach ($selections as $selection) {
642: if ($selection->getSelectionCanChangeQty() && isset($qtys[$selection->getOptionId()])) {
643: $qty = (float)$qtys[$selection->getOptionId()] > 0 ? $qtys[$selection->getOptionId()] : 1;
644: } else {
645: $qty = (float)$selection->getSelectionQty() ? $selection->getSelectionQty() : 1;
646: }
647: $qty = (float)$qty;
648:
649: $product->addCustomOption('selection_qty_' . $selection->getSelectionId(), $qty, $selection);
650: $selection->addCustomOption('selection_id', $selection->getSelectionId());
651:
652: $beforeQty = 0;
653: $customOption = $product->getCustomOption('product_qty_' . $selection->getId());
654: if ($customOption) {
655: $beforeQty = (float)$customOption->getValue();
656: }
657: $product->addCustomOption('product_qty_' . $selection->getId(), $qty + $beforeQty, $selection);
658:
659: 660: 661: 662:
663: $price = $product->getPriceModel()->getSelectionFinalTotalPrice($product, $selection, 0, $qty);
664: $attributes = array(
665: 'price' => Mage::app()->getStore()->convertPrice($price),
666: 'qty' => $qty,
667: 'option_label' => $selection->getOption()->getTitle(),
668: 'option_id' => $selection->getOption()->getId()
669: );
670:
671: $_result = $selection->getTypeInstance(true)->prepareForCart($buyRequest, $selection);
672: if (is_string($_result) && !is_array($_result)) {
673: return $_result;
674: }
675:
676: if (!isset($_result[0])) {
677: return Mage::helper('checkout')->__('Cannot add item to the shopping cart.');
678: }
679:
680: $result[] = $_result[0]->setParentProductId($product->getId())
681: ->addCustomOption('bundle_option_ids', serialize(array_map('intval', $optionIds)))
682: ->addCustomOption('bundle_selection_attributes', serialize($attributes));
683:
684: if ($isStrictProcessMode) {
685: $_result[0]->setCartQty($qty);
686: }
687:
688: $selectionIds[] = $_result[0]->getSelectionId();
689: $uniqueKey[] = $_result[0]->getSelectionId();
690: $uniqueKey[] = $qty;
691: }
692:
693:
694: $uniqueKey = implode('_', $uniqueKey);
695: foreach ($result as $item) {
696: $item->addCustomOption('bundle_identity', $uniqueKey);
697: }
698: $product->addCustomOption('bundle_option_ids', serialize(array_map('intval', $optionIds)));
699: $product->addCustomOption('bundle_selection_ids', serialize($selectionIds));
700:
701: return $result;
702: }
703:
704: return $this->getSpecifyOptionMessage();
705: }
706:
707: 708: 709: 710: 711:
712: public function getSpecifyOptionMessage()
713: {
714: return Mage::helper('bundle')->__('Please specify product option(s).');
715: }
716:
717: 718: 719: 720: 721: 722: 723:
724: public function getSelectionsByIds($selectionIds, $product = null)
725: {
726: sort($selectionIds);
727:
728: $usedSelections = $this->getProduct($product)->getData($this->_keyUsedSelections);
729: $usedSelectionsIds = $this->getProduct($product)->getData($this->_keyUsedSelectionsIds);
730:
731: if (!$usedSelections || serialize($usedSelectionsIds) != serialize($selectionIds)) {
732: $storeId = $this->getProduct($product)->getStoreId();
733: $usedSelections = Mage::getResourceModel('bundle/selection_collection')
734: ->addAttributeToSelect('*')
735: ->setFlag('require_stock_items', true)
736: ->addStoreFilter($this->getStoreFilter($product))
737: ->setStoreId($storeId)
738: ->setPositionOrder()
739: ->addFilterByRequiredOptions()
740: ->setSelectionIdsFilter($selectionIds);
741:
742: if (!Mage::helper('catalog')->isPriceGlobal() && $storeId) {
743: $websiteId = Mage::app()->getStore($storeId)->getWebsiteId();
744: $usedSelections->joinPrices($websiteId);
745: }
746: $this->getProduct($product)->setData($this->_keyUsedSelections, $usedSelections);
747: $this->getProduct($product)->setData($this->_keyUsedSelectionsIds, $selectionIds);
748: }
749: return $usedSelections;
750: }
751:
752: 753: 754: 755: 756: 757: 758:
759: public function getOptionsByIds($optionIds, $product = null)
760: {
761: sort($optionIds);
762:
763: $usedOptions = $this->getProduct($product)->getData($this->_keyUsedOptions);
764: $usedOptionsIds = $this->getProduct($product)->getData($this->_keyUsedOptionsIds);
765:
766: if (!$usedOptions || serialize($usedOptionsIds) != serialize($optionIds)) {
767: $usedOptions = Mage::getModel('bundle/option')->getResourceCollection()
768: ->setProductIdFilter($this->getProduct($product)->getId())
769: ->setPositionOrder()
770: ->joinValues(Mage::app()->getStore()->getId())
771: ->setIdFilter($optionIds);
772: $this->getProduct($product)->setData($this->_keyUsedOptions, $usedOptions);
773: $this->getProduct($product)->setData($this->_keyUsedOptionsIds, $optionIds);
774: }
775: return $usedOptions;
776: }
777:
778: 779: 780: 781: 782: 783: 784:
785: public function getOrderOptions($product = null)
786: {
787: $optionArr = parent::getOrderOptions($product);
788:
789: $bundleOptions = array();
790:
791: $product = $this->getProduct($product);
792:
793: if ($product->hasCustomOptions()) {
794: $customOption = $product->getCustomOption('bundle_option_ids');
795: $optionIds = unserialize($customOption->getValue());
796: $options = $this->getOptionsByIds($optionIds, $product);
797: $customOption = $product->getCustomOption('bundle_selection_ids');
798: $selectionIds = unserialize($customOption->getValue());
799: $selections = $this->getSelectionsByIds($selectionIds, $product);
800: foreach ($selections->getItems() as $selection) {
801: if ($selection->isSalable()) {
802: $selectionQty = $product->getCustomOption('selection_qty_' . $selection->getSelectionId());
803: if ($selectionQty) {
804: $price = $product->getPriceModel()->getSelectionFinalTotalPrice($product, $selection, 0,
805: $selectionQty->getValue()
806: );
807:
808: $option = $options->getItemById($selection->getOptionId());
809: if (!isset($bundleOptions[$option->getId()])) {
810: $bundleOptions[$option->getId()] = array(
811: 'option_id' => $option->getId(),
812: 'label' => $option->getTitle(),
813: 'value' => array()
814: );
815: }
816:
817: $bundleOptions[$option->getId()]['value'][] = array(
818: 'title' => $selection->getName(),
819: 'qty' => $selectionQty->getValue(),
820: 'price' => Mage::app()->getStore()->convertPrice($price)
821: );
822:
823: }
824: }
825: }
826: }
827:
828: $optionArr['bundle_options'] = $bundleOptions;
829:
830: 831: 832:
833: if ($product->getPriceType()) {
834: $optionArr['product_calculations'] = self::CALCULATE_PARENT;
835: } else {
836: $optionArr['product_calculations'] = self::CALCULATE_CHILD;
837: }
838:
839: $optionArr['shipment_type'] = $product->getShipmentType();
840:
841: return $optionArr;
842: }
843:
844: 845: 846: 847: 848: 849: 850: 851:
852: public function shakeSelections($a, $b)
853: {
854: $aPosition = array(
855: $a->getOption()->getPosition(),
856: $a->getOptionId(),
857: $a->getPosition(),
858: $a->getSelectionId()
859: );
860: $bPosition = array(
861: $b->getOption()->getPosition(),
862: $b->getOptionId(),
863: $b->getPosition(),
864: $b->getSelectionId()
865: );
866: if ($aPosition == $bPosition) {
867: return 0;
868: } else {
869: return $aPosition < $bPosition ? -1 : 1;
870: }
871: }
872:
873: 874: 875: 876: 877: 878:
879: public function hasOptions($product = null)
880: {
881: $product = $this->getProduct($product);
882: $this->setStoreFilter($product->getStoreId(), $product);
883: $optionIds = $this->getOptionsCollection($product)->getAllIds();
884: $collection = $this->getSelectionsCollection($optionIds, $product);
885:
886: if (count($collection) > 0 || $product->getOptions()) {
887: return true;
888: }
889:
890: return false;
891: }
892:
893: 894: 895: 896: 897: 898:
899: public function getForceChildItemQtyChanges($product = null)
900: {
901: return true;
902: }
903:
904: 905: 906: 907: 908: 909: 910:
911: public function getSearchableData($product = null)
912: {
913: $searchData = parent::getSearchableData($product);
914: $product = $this->getProduct($product);
915:
916: $optionSearchData = Mage::getSingleton('bundle/option')
917: ->getSearchableData($product->getId(), $product->getStoreId());
918: if ($optionSearchData) {
919: $searchData = array_merge($searchData, $optionSearchData);
920: }
921:
922: return $searchData;
923: }
924:
925: 926: 927: 928: 929: 930: 931:
932: public function checkProductBuyState($product = null)
933: {
934: parent::checkProductBuyState($product);
935: $product = $this->getProduct($product);
936: $productOptionIds = $this->getOptionsIds($product);
937: $productSelections = $this->getSelectionsCollection($productOptionIds, $product);
938: $selectionIds = $product->getCustomOption('bundle_selection_ids');
939: $selectionIds = unserialize($selectionIds->getValue());
940: $buyRequest = $product->getCustomOption('info_buyRequest');
941: $buyRequest = new Varien_Object(unserialize($buyRequest->getValue()));
942: $bundleOption = $buyRequest->getBundleOption();
943:
944: if (empty($bundleOption)) {
945: Mage::throwException($this->getSpecifyOptionMessage());
946: }
947:
948: $skipSaleableCheck = Mage::helper('catalog/product')->getSkipSaleableCheck();
949: foreach ($selectionIds as $selectionId) {
950:
951: $selection = $productSelections->getItemById($selectionId);
952: if (!$selection || (!$selection->isSalable() && !$skipSaleableCheck)) {
953: Mage::throwException(
954: Mage::helper('bundle')->__('Selected required options are not available.')
955: );
956: }
957: }
958:
959: $product->getTypeInstance(true)->setStoreFilter($product->getStoreId(), $product);
960: $optionsCollection = $this->getOptionsCollection($product);
961: foreach ($optionsCollection->getItems() as $option) {
962: if ($option->getRequired() && empty($bundleOption[$option->getId()])) {
963: Mage::throwException(
964: Mage::helper('bundle')->__('Required options are not selected.')
965: );
966: }
967: }
968:
969: return $this;
970: }
971:
972: 973: 974: 975: 976: 977: 978:
979: public function getProductsToPurchaseByReqGroups($product = null)
980: {
981: $product = $this->getProduct($product);
982: $groups = array();
983: $allProducts = array();
984: $hasRequiredOptions = false;
985: foreach ($this->getOptions($product) as $option) {
986: $groupProducts = array();
987: foreach ($this->getSelectionsCollection(array($option->getId()), $product) as $childProduct) {
988: $groupProducts[] = $childProduct;
989: $allProducts[] = $childProduct;
990: }
991: if ($option->getRequired()) {
992: $groups[] = $groupProducts;
993: $hasRequiredOptions = true;
994: }
995: }
996: if (!$hasRequiredOptions) {
997: $groups = array($allProducts);
998: }
999: return $groups;
1000: }
1001:
1002: 1003: 1004: 1005: 1006: 1007: 1008:
1009: public function processBuyRequest($product, $buyRequest)
1010: {
1011: $option = $buyRequest->getBundleOption();
1012: $optionQty = $buyRequest->getBundleOptionQty();
1013:
1014: $option = (is_array($option)) ? array_filter($option, 'intval') : array();
1015: $optionQty = (is_array($optionQty)) ? array_filter($optionQty, 'intval') : array();
1016:
1017: $options = array(
1018: 'bundle_option' => $option,
1019: 'bundle_option_qty' => $optionQty
1020: );
1021:
1022: return $options;
1023: }
1024:
1025: 1026: 1027: 1028: 1029: 1030:
1031: public function canConfigure($product = null)
1032: {
1033: return $product instanceof Mage_Catalog_Model_Product
1034: && $product->isAvailable()
1035: && parent::canConfigure();
1036: }
1037:
1038: 1039: 1040: 1041: 1042: 1043: 1044:
1045: public function isMapEnabledInOptions($product, $visibility = null)
1046: {
1047: 1048: 1049: 1050:
1051: 1052: 1053: 1054: 1055: 1056: 1057: 1058: 1059: 1060: 1061: 1062: 1063: 1064: 1065: 1066: 1067: 1068: 1069: 1070: 1071: 1072: 1073: 1074: 1075: 1076: 1077: 1078: 1079: 1080: 1081: 1082:
1083:
1084: return null;
1085: }
1086: }
1087: