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_Sales
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: * Sales Quote Item Model
30: *
31: * @method Mage_Sales_Model_Resource_Quote_Item _getResource()
32: * @method Mage_Sales_Model_Resource_Quote_Item getResource()
33: * @method int getQuoteId()
34: * @method Mage_Sales_Model_Quote_Item setQuoteId(int $value)
35: * @method string getCreatedAt()
36: * @method Mage_Sales_Model_Quote_Item setCreatedAt(string $value)
37: * @method string getUpdatedAt()
38: * @method Mage_Sales_Model_Quote_Item setUpdatedAt(string $value)
39: * @method int getProductId()
40: * @method Mage_Sales_Model_Quote_Item setProductId(int $value)
41: * @method int getStoreId()
42: * @method Mage_Sales_Model_Quote_Item setStoreId(int $value)
43: * @method int getParentItemId()
44: * @method Mage_Sales_Model_Quote_Item setParentItemId(int $value)
45: * @method int getIsVirtual()
46: * @method Mage_Sales_Model_Quote_Item setIsVirtual(int $value)
47: * @method string getSku()
48: * @method Mage_Sales_Model_Quote_Item setSku(string $value)
49: * @method string getName()
50: * @method Mage_Sales_Model_Quote_Item setName(string $value)
51: * @method string getDescription()
52: * @method Mage_Sales_Model_Quote_Item setDescription(string $value)
53: * @method string getAppliedRuleIds()
54: * @method Mage_Sales_Model_Quote_Item setAppliedRuleIds(string $value)
55: * @method string getAdditionalData()
56: * @method Mage_Sales_Model_Quote_Item setAdditionalData(string $value)
57: * @method int getFreeShipping()
58: * @method Mage_Sales_Model_Quote_Item setFreeShipping(int $value)
59: * @method int getIsQtyDecimal()
60: * @method Mage_Sales_Model_Quote_Item setIsQtyDecimal(int $value)
61: * @method int getNoDiscount()
62: * @method Mage_Sales_Model_Quote_Item setNoDiscount(int $value)
63: * @method float getWeight()
64: * @method Mage_Sales_Model_Quote_Item setWeight(float $value)
65: * @method float getBasePrice()
66: * @method Mage_Sales_Model_Quote_Item setBasePrice(float $value)
67: * @method float getCustomPrice()
68: * @method float getDiscountPercent()
69: * @method Mage_Sales_Model_Quote_Item setDiscountPercent(float $value)
70: * @method float getDiscountAmount()
71: * @method Mage_Sales_Model_Quote_Item setDiscountAmount(float $value)
72: * @method float getBaseDiscountAmount()
73: * @method Mage_Sales_Model_Quote_Item setBaseDiscountAmount(float $value)
74: * @method float getTaxPercent()
75: * @method Mage_Sales_Model_Quote_Item setTaxPercent(float $value)
76: * @method Mage_Sales_Model_Quote_Item setTaxAmount(float $value)
77: * @method Mage_Sales_Model_Quote_Item setBaseTaxAmount(float $value)
78: * @method float getRowTotal()
79: * @method Mage_Sales_Model_Quote_Item setRowTotal(float $value)
80: * @method float getBaseRowTotal()
81: * @method Mage_Sales_Model_Quote_Item setBaseRowTotal(float $value)
82: * @method float getRowTotalWithDiscount()
83: * @method Mage_Sales_Model_Quote_Item setRowTotalWithDiscount(float $value)
84: * @method float getRowWeight()
85: * @method Mage_Sales_Model_Quote_Item setRowWeight(float $value)
86: * @method Mage_Sales_Model_Quote_Item setProductType(string $value)
87: * @method float getBaseTaxBeforeDiscount()
88: * @method Mage_Sales_Model_Quote_Item setBaseTaxBeforeDiscount(float $value)
89: * @method float getTaxBeforeDiscount()
90: * @method Mage_Sales_Model_Quote_Item setTaxBeforeDiscount(float $value)
91: * @method float getOriginalCustomPrice()
92: * @method Mage_Sales_Model_Quote_Item setOriginalCustomPrice(float $value)
93: * @method string getRedirectUrl()
94: * @method Mage_Sales_Model_Quote_Item setRedirectUrl(string $value)
95: * @method float getBaseCost()
96: * @method Mage_Sales_Model_Quote_Item setBaseCost(float $value)
97: * @method float getPriceInclTax()
98: * @method Mage_Sales_Model_Quote_Item setPriceInclTax(float $value)
99: * @method float getBasePriceInclTax()
100: * @method Mage_Sales_Model_Quote_Item setBasePriceInclTax(float $value)
101: * @method float getRowTotalInclTax()
102: * @method Mage_Sales_Model_Quote_Item setRowTotalInclTax(float $value)
103: * @method float getBaseRowTotalInclTax()
104: * @method Mage_Sales_Model_Quote_Item setBaseRowTotalInclTax(float $value)
105: * @method int getGiftMessageId()
106: * @method Mage_Sales_Model_Quote_Item setGiftMessageId(int $value)
107: * @method string getWeeeTaxApplied()
108: * @method Mage_Sales_Model_Quote_Item setWeeeTaxApplied(string $value)
109: * @method float getWeeeTaxAppliedAmount()
110: * @method Mage_Sales_Model_Quote_Item setWeeeTaxAppliedAmount(float $value)
111: * @method float getWeeeTaxAppliedRowAmount()
112: * @method Mage_Sales_Model_Quote_Item setWeeeTaxAppliedRowAmount(float $value)
113: * @method float getBaseWeeeTaxAppliedAmount()
114: * @method Mage_Sales_Model_Quote_Item setBaseWeeeTaxAppliedAmount(float $value)
115: * @method float getBaseWeeeTaxAppliedRowAmount()
116: * @method Mage_Sales_Model_Quote_Item setBaseWeeeTaxAppliedRowAmount(float $value)
117: * @method float getWeeeTaxDisposition()
118: * @method Mage_Sales_Model_Quote_Item setWeeeTaxDisposition(float $value)
119: * @method float getWeeeTaxRowDisposition()
120: * @method Mage_Sales_Model_Quote_Item setWeeeTaxRowDisposition(float $value)
121: * @method float getBaseWeeeTaxDisposition()
122: * @method Mage_Sales_Model_Quote_Item setBaseWeeeTaxDisposition(float $value)
123: * @method float getBaseWeeeTaxRowDisposition()
124: * @method Mage_Sales_Model_Quote_Item setBaseWeeeTaxRowDisposition(float $value)
125: * @method float getHiddenTaxAmount()
126: * @method Mage_Sales_Model_Quote_Item setHiddenTaxAmount(float $value)
127: * @method float getBaseHiddenTaxAmount()
128: * @method Mage_Sales_Model_Quote_Item setBaseHiddenTaxAmount(float $value)
129: *
130: * @category Mage
131: * @package Mage_Sales
132: * @author Magento Core Team <core@magentocommerce.com>
133: */
134: class Mage_Sales_Model_Quote_Item extends Mage_Sales_Model_Quote_Item_Abstract
135: {
136: /**
137: * Prefix of model events names
138: *
139: * @var string
140: */
141: protected $_eventPrefix = 'sales_quote_item';
142:
143: /**
144: * Parameter name in event
145: *
146: * In observe method you can use $observer->getEvent()->getObject() in this case
147: *
148: * @var string
149: */
150: protected $_eventObject = 'item';
151:
152: /**
153: * Quote model object
154: *
155: * @var Mage_Sales_Model_Quote
156: */
157: protected $_quote;
158:
159: /**
160: * Item options array
161: *
162: * @var array
163: */
164: protected $_options = array();
165:
166: /**
167: * Item options by code cache
168: *
169: * @var array
170: */
171: protected $_optionsByCode = array();
172:
173: /**
174: * Not Represent options
175: *
176: * @var array
177: */
178: protected $_notRepresentOptions = array('info_buyRequest');
179:
180: /**
181: * Flag stating that options were successfully saved
182: *
183: */
184: protected $_flagOptionsSaved = null;
185:
186: /**
187: * Array of errors associated with this quote item
188: *
189: * @var Mage_Sales_Model_Status_List
190: */
191: protected $_errorInfos = null;
192:
193: /**
194: * Initialize resource model
195: *
196: */
197: protected function _construct()
198: {
199: $this->_init('sales/quote_item');
200: $this->_errorInfos = Mage::getModel('sales/status_list');
201: }
202:
203: /**
204: * Init mapping array of short fields to
205: * its full names
206: *
207: * @return Varien_Object
208: */
209: protected function _initOldFieldsMap()
210: {
211: $this->_oldFieldsMap = Mage::helper('sales')->getOldFieldMap('quote_item');
212: return $this;
213: }
214:
215: /**
216: * Quote Item Before Save prepare data process
217: *
218: * @return Mage_Sales_Model_Quote_Item
219: */
220: protected function _beforeSave()
221: {
222: parent::_beforeSave();
223: $this->setIsVirtual($this->getProduct()->getIsVirtual());
224: if ($this->getQuote()) {
225: $this->setQuoteId($this->getQuote()->getId());
226: }
227: return $this;
228: }
229:
230: /**
231: * Declare quote model object
232: *
233: * @param Mage_Sales_Model_Quote $quote
234: * @return Mage_Sales_Model_Quote_Item
235: */
236: public function setQuote(Mage_Sales_Model_Quote $quote)
237: {
238: $this->_quote = $quote;
239: $this->setQuoteId($quote->getId());
240: return $this;
241: }
242:
243: /**
244: * Retrieve quote model object
245: *
246: * @return Mage_Sales_Model_Quote
247: */
248: public function getQuote()
249: {
250: return $this->_quote;
251: }
252:
253: /**
254: * Prepare quantity
255: *
256: * @param float|int $qty
257: * @return int|float
258: */
259: protected function _prepareQty($qty)
260: {
261: $qty = Mage::app()->getLocale()->getNumber($qty);
262: $qty = ($qty > 0) ? $qty : 1;
263: return $qty;
264: }
265:
266: /**
267: * Adding quantity to quote item
268: *
269: * @param float $qty
270: * @return Mage_Sales_Model_Quote_Item
271: */
272: public function addQty($qty)
273: {
274: $oldQty = $this->getQty();
275: $qty = $this->_prepareQty($qty);
276:
277: /**
278: * We can't modify quontity of existing items which have parent
279: * This qty declared just once duering add process and is not editable
280: */
281: if (!$this->getParentItem() || !$this->getId()) {
282: $this->setQtyToAdd($qty);
283: $this->setQty($oldQty+$qty);
284: }
285: return $this;
286: }
287:
288: /**
289: * Declare quote item quantity
290: *
291: * @param float $qty
292: * @return Mage_Sales_Model_Quote_Item
293: */
294: public function setQty($qty)
295: {
296: $qty = $this->_prepareQty($qty);
297: $oldQty = $this->_getData('qty');
298: $this->setData('qty', $qty);
299:
300: Mage::dispatchEvent('sales_quote_item_qty_set_after', array('item'=>$this));
301:
302: if ($this->getQuote() && $this->getQuote()->getIgnoreOldQty()) {
303: return $this;
304: }
305: if ($this->getUseOldQty()) {
306: $this->setData('qty', $oldQty);
307: }
308:
309: return $this;
310: }
311:
312: /**
313: * Retrieve option product with Qty
314: *
315: * Return array
316: * 'qty' => the qty
317: * 'product' => the product model
318: *
319: * @return array
320: */
321: public function getQtyOptions()
322: {
323: $qtyOptions = $this->getData('qty_options');
324: if (is_null($qtyOptions)) {
325: $productIds = array();
326: $qtyOptions = array();
327: foreach ($this->getOptions() as $option) {
328: /** @var $option Mage_Sales_Model_Quote_Item_Option */
329: if (is_object($option->getProduct())
330: && $option->getProduct()->getId() != $this->getProduct()->getId()
331: ) {
332: $productIds[$option->getProduct()->getId()] = $option->getProduct()->getId();
333: }
334: }
335:
336: foreach ($productIds as $productId) {
337: $option = $this->getOptionByCode('product_qty_' . $productId);
338: if ($option) {
339: $qtyOptions[$productId] = $option;
340: }
341: }
342:
343: $this->setData('qty_options', $qtyOptions);
344: }
345:
346: return $qtyOptions;
347: }
348:
349: /**
350: * Set option product with Qty
351: *
352: * @param $qtyOptions
353: * @return Mage_Sales_Model_Quote_Item
354: */
355: public function setQtyOptions($qtyOptions)
356: {
357: return $this->setData('qty_options', $qtyOptions);
358: }
359:
360: /**
361: * Checking item data
362: *
363: * @return Mage_Sales_Model_Quote_Item_Abstract
364: */
365: public function checkData()
366: {
367: $parent = parent::checkData();
368: if ($this->getProduct()->getHasError()) {
369: $this->setHasError(true);
370: $this->setMessage(Mage::helper('sales')->__('Item options declaration error.'));
371: $this->getQuote()->setHasError(true);
372: $this->getQuote()->addMessage($this->getProduct()->getMessage(), 'options');
373: }
374: return $parent;
375: }
376:
377: /**
378: * Setup product for quote item
379: *
380: * @param Mage_Catalog_Model_Product $product
381: * @return Mage_Sales_Model_Quote_Item
382: */
383: public function setProduct($product)
384: {
385: if ($this->getQuote()) {
386: $product->setStoreId($this->getQuote()->getStoreId());
387: $product->setCustomerGroupId($this->getQuote()->getCustomerGroupId());
388: }
389: $this->setData('product', $product)
390: ->setProductId($product->getId())
391: ->setProductType($product->getTypeId())
392: ->setSku($this->getProduct()->getSku())
393: ->setName($product->getName())
394: ->setWeight($this->getProduct()->getWeight())
395: ->setTaxClassId($product->getTaxClassId())
396: ->setBaseCost($product->getCost())
397: ->setIsRecurring($product->getIsRecurring())
398: ;
399:
400: if ($product->getStockItem()) {
401: $this->setIsQtyDecimal($product->getStockItem()->getIsQtyDecimal());
402: }
403:
404: Mage::dispatchEvent('sales_quote_item_set_product', array(
405: 'product' => $product,
406: 'quote_item'=>$this
407: ));
408:
409:
410: // if ($options = $product->getCustomOptions()) {
411: // foreach ($options as $option) {
412: // $this->addOption($option);
413: // }
414: // }
415: return $this;
416: }
417:
418: /**
419: * Check product representation in item
420: *
421: * @param Mage_Catalog_Model_Product $product
422: * @return bool
423: */
424: public function representProduct($product)
425: {
426: $itemProduct = $this->getProduct();
427: if (!$product || $itemProduct->getId() != $product->getId()) {
428: return false;
429: }
430:
431: /**
432: * Check maybe product is planned to be a child of some quote item - in this case we limit search
433: * only within same parent item
434: */
435: $stickWithinParent = $product->getStickWithinParent();
436: if ($stickWithinParent) {
437: if ($this->getParentItem() !== $stickWithinParent) {
438: return false;
439: }
440: }
441:
442: // Check options
443: $itemOptions = $this->getOptionsByCode();
444: $productOptions = $product->getCustomOptions();
445:
446: if(!$this->compareOptions($itemOptions, $productOptions)){
447: return false;
448: }
449: if(!$this->compareOptions($productOptions, $itemOptions)){
450: return false;
451: }
452: return true;
453: }
454:
455: /**
456: * Check if two options array are identical
457: * First options array is prerogative
458: * Second options array checked against first one
459: *
460: * @param array $options1
461: * @param array $options2
462: * @return bool
463: */
464: public function compareOptions($options1, $options2)
465: {
466: foreach ($options1 as $option) {
467: $code = $option->getCode();
468: if (in_array($code, $this->_notRepresentOptions )) {
469: continue;
470: }
471: if ( !isset($options2[$code])
472: || ($options2[$code]->getValue() === null)
473: || $options2[$code]->getValue() != $option->getValue()) {
474: return false;
475: }
476: }
477: return true;
478: }
479:
480: /**
481: * Compare item
482: *
483: * @param Mage_Sales_Model_Quote_Item $item
484: * @return bool
485: */
486: public function compare($item)
487: {
488: if ($this->getProductId() != $item->getProductId()) {
489: return false;
490: }
491: foreach ($this->getOptions() as $option) {
492: if (in_array($option->getCode(), $this->_notRepresentOptions)) {
493: continue;
494: }
495: if ($itemOption = $item->getOptionByCode($option->getCode())) {
496: $itemOptionValue = $itemOption->getValue();
497: $optionValue = $option->getValue();
498:
499: // dispose of some options params, that can cramp comparing of arrays
500: if (is_string($itemOptionValue) && is_string($optionValue)) {
501: $_itemOptionValue = @unserialize($itemOptionValue);
502: $_optionValue = @unserialize($optionValue);
503: if (is_array($_itemOptionValue) && is_array($_optionValue)) {
504: $itemOptionValue = $_itemOptionValue;
505: $optionValue = $_optionValue;
506: // looks like it does not break bundle selection qty
507: unset($itemOptionValue['qty'], $itemOptionValue['uenc']);
508: unset($optionValue['qty'], $optionValue['uenc']);
509: }
510: }
511:
512: if ($itemOptionValue != $optionValue) {
513: return false;
514: }
515: }
516: else {
517: return false;
518: }
519: }
520: return true;
521: }
522:
523: /**
524: * Get item product type
525: *
526: * @return string
527: */
528: public function getProductType()
529: {
530: if ($option = $this->getOptionByCode('product_type')) {
531: return $option->getValue();
532: }
533: if ($product = $this->getProduct()) {
534: return $product->getTypeId();
535: }
536: return $this->_getData('product_type');
537: }
538:
539: /**
540: * Return real product type of item
541: *
542: * @return unknown
543: */
544: public function getRealProductType()
545: {
546: return $this->_getData('product_type');
547: }
548:
549: /**
550: * Convert Quote Item to array
551: *
552: * @param array $arrAttributes
553: * @return array
554: */
555: public function toArray(array $arrAttributes=array())
556: {
557: $data = parent::toArray($arrAttributes);
558:
559: if ($product = $this->getProduct()) {
560: $data['product'] = $product->toArray();
561: }
562: return $data;
563: }
564:
565: /**
566: * Initialize quote item options
567: *
568: * @param array $options
569: * @return Mage_Sales_Model_Quote_Item
570: */
571: public function setOptions($options)
572: {
573: foreach ($options as $option) {
574: $this->addOption($option);
575: }
576: return $this;
577: }
578:
579: /**
580: * Get all item options
581: *
582: * @return array
583: */
584: public function getOptions()
585: {
586: return $this->_options;
587: }
588:
589: /**
590: * Get all item options as array with codes in array key
591: *
592: * @return array
593: */
594: public function getOptionsByCode()
595: {
596: return $this->_optionsByCode;
597: }
598:
599: /**
600: * Add option to item
601: *
602: * @param Mage_Sales_Model_Quote_Item_Option|Varien_Object $option
603: * @return Mage_Sales_Model_Quote_Item
604: */
605: public function addOption($option)
606: {
607: if (is_array($option)) {
608: $option = Mage::getModel('sales/quote_item_option')->setData($option)
609: ->setItem($this);
610: }
611: elseif (($option instanceof Varien_Object) && !($option instanceof Mage_Sales_Model_Quote_Item_Option)) {
612: $option = Mage::getModel('sales/quote_item_option')->setData($option->getData())
613: ->setProduct($option->getProduct())
614: ->setItem($this);
615: }
616: elseif($option instanceof Mage_Sales_Model_Quote_Item_Option) {
617: $option->setItem($this);
618: }
619: else {
620: Mage::throwException(Mage::helper('sales')->__('Invalid item option format.'));
621: }
622:
623: if ($exOption = $this->getOptionByCode($option->getCode())) {
624: $exOption->addData($option->getData());
625: }
626: else {
627: $this->_addOptionCode($option);
628: $this->_options[] = $option;
629: }
630: return $this;
631: }
632:
633: /**
634: * Can specify specific actions for ability to change given quote options values
635: * Exemple: cataloginventory decimal qty validation may change qty to int,
636: * so need to change quote item qty option value.
637: *
638: * @param array $options
639: * @param Varien_Object $option
640: * @param mixed $value
641: *
642: * @return object Mage_Catalog_Model_Product_Type_Abstract
643: */
644: public function updateQtyOption(Varien_Object $option, $value)
645: {
646: $optionProduct = $option->getProduct();
647: $options = $this->getQtyOptions();
648:
649: if (isset($options[$optionProduct->getId()])) {
650: $options[$optionProduct->getId()]->setValue($value);
651: }
652:
653: $this->getProduct()->getTypeInstance(true)
654: ->updateQtyOption($this->getOptions(), $option, $value, $this->getProduct());
655:
656: return $this;
657: }
658:
659: /**
660: *Remove option from item options
661: *
662: * @param string $code
663: * @return Mage_Sales_Model_Quote_Item
664: */
665: public function removeOption($code)
666: {
667: $option = $this->getOptionByCode($code);
668: if ($option) {
669: $option->isDeleted(true);
670: }
671: return $this;
672: }
673:
674: /**
675: * Register option code
676: *
677: * @param Mage_Sales_Model_Quote_Item_Option $option
678: * @return Mage_Sales_Model_Quote_Item
679: */
680: protected function _addOptionCode($option)
681: {
682: if (!isset($this->_optionsByCode[$option->getCode()])) {
683: $this->_optionsByCode[$option->getCode()] = $option;
684: }
685: else {
686: Mage::throwException(Mage::helper('sales')->__('An item option with code %s already exists.', $option->getCode()));
687: }
688: return $this;
689: }
690:
691: /**
692: * Get item option by code
693: *
694: * @param string $code
695: * @return Mage_Sales_Model_Quote_Item_Option || null
696: */
697: public function getOptionByCode($code)
698: {
699: if (isset($this->_optionsByCode[$code]) && !$this->_optionsByCode[$code]->isDeleted()) {
700: return $this->_optionsByCode[$code];
701: }
702: return null;
703: }
704:
705: /**
706: * Checks that item model has data changes.
707: * Call save item options if model isn't need to save in DB
708: *
709: * @return boolean
710: */
711: protected function _hasModelChanged()
712: {
713: if (!$this->hasDataChanges()) {
714: return false;
715: }
716:
717: return $this->_getResource()->hasDataChanged($this);
718: }
719:
720: /**
721: * Save item options
722: *
723: * @return Mage_Sales_Model_Quote_Item
724: */
725: protected function _saveItemOptions()
726: {
727: foreach ($this->_options as $index => $option) {
728: if ($option->isDeleted()) {
729: $option->delete();
730: unset($this->_options[$index]);
731: unset($this->_optionsByCode[$option->getCode()]);
732: } else {
733: $option->save();
734: }
735: }
736:
737: $this->_flagOptionsSaved = true; // Report to watchers that options were saved
738:
739: return $this;
740: }
741:
742: /**
743: * Save model plus its options
744: * Ensures saving options in case when resource model was not changed
745: */
746: public function save()
747: {
748: $hasDataChanges = $this->hasDataChanges();
749: $this->_flagOptionsSaved = false;
750:
751: parent::save();
752:
753: if ($hasDataChanges && !$this->_flagOptionsSaved) {
754: $this->_saveItemOptions();
755: }
756: }
757:
758: /**
759: * Save item options after item saved
760: *
761: * @return Mage_Sales_Model_Quote_Item
762: */
763: protected function _afterSave()
764: {
765: $this->_saveItemOptions();
766: return parent::_afterSave();
767: }
768:
769: /**
770: * Clone quote item
771: *
772: * @return Mage_Sales_Model_Quote_Item
773: */
774: public function __clone()
775: {
776: parent::__clone();
777: $options = $this->getOptions();
778: $this->_quote = null;
779: $this->_options = array();
780: $this->_optionsByCode = array();
781: foreach ($options as $option) {
782: $this->addOption(clone $option);
783: }
784: return $this;
785: }
786:
787: /**
788: * Returns formatted buy request - object, holding request received from
789: * product view page with keys and options for configured product
790: *
791: * @return Varien_Object
792: */
793: public function getBuyRequest()
794: {
795: $option = $this->getOptionByCode('info_buyRequest');
796: $buyRequest = new Varien_Object($option ? unserialize($option->getValue()) : null);
797:
798: // Overwrite standard buy request qty, because item qty could have changed since adding to quote
799: $buyRequest->setOriginalQty($buyRequest->getQty())
800: ->setQty($this->getQty() * 1);
801:
802: return $buyRequest;
803: }
804:
805: /**
806: * Sets flag, whether this quote item has some error associated with it.
807: *
808: * @param bool $flag
809: * @return Mage_Sales_Model_Quote_Item
810: */
811: protected function _setHasError($flag)
812: {
813: return $this->setData('has_error', $flag);
814: }
815:
816: /**
817: * Sets flag, whether this quote item has some error associated with it.
818: * When TRUE - also adds 'unknown' error information to list of quote item errors.
819: * When FALSE - clears whole list of quote item errors.
820: * It's recommended to use addErrorInfo() instead - to be able to remove error statuses later.
821: *
822: * @param bool $flag
823: * @return Mage_Sales_Model_Quote_Item
824: * @see addErrorInfo()
825: */
826: public function setHasError($flag)
827: {
828: if ($flag) {
829: $this->addErrorInfo();
830: } else {
831: $this->_clearErrorInfo();
832: }
833: return $this;
834: }
835:
836: /**
837: * Clears list of errors, associated with this quote item.
838: * Also automatically removes error-flag from oneself.
839: *
840: * @return Mage_Sales_Model_Quote_Item
841: */
842: protected function _clearErrorInfo()
843: {
844: $this->_errorInfos->clear();
845: $this->_setHasError(false);
846: return $this;
847: }
848:
849: /**
850: * Adds error information to the quote item.
851: * Automatically sets error flag.
852: *
853: * @param string|null $origin Usually a name of module, that embeds error
854: * @param int|null $code Error code, unique for origin, that sets it
855: * @param string|null $message Error message
856: * @param Varien_Object|null $additionalData Any additional data, that caller would like to store
857: * @return Mage_Sales_Model_Quote_Item
858: */
859: public function addErrorInfo($origin = null, $code = null, $message = null, $additionalData = null)
860: {
861: $this->_errorInfos->addItem($origin, $code, $message, $additionalData);
862: if ($message !== null) {
863: $this->setMessage($message);
864: }
865: $this->_setHasError(true);
866:
867: return $this;
868: }
869:
870: /**
871: * Retrieves all error infos, associated with this item
872: *
873: * @return array
874: */
875: public function getErrorInfos()
876: {
877: return $this->_errorInfos->getItems();
878: }
879:
880: /**
881: * Removes error infos, that have parameters equal to passed in $params.
882: * $params can have following keys (if not set - then any item is good for this key):
883: * 'origin', 'code', 'message'
884: *
885: * @param array $params
886: * @return Mage_Sales_Model_Quote_Item
887: */
888: public function removeErrorInfosByParams($params)
889: {
890: $removedItems = $this->_errorInfos->removeItemsByParams($params);
891: foreach ($removedItems as $item) {
892: if ($item['message'] !== null) {
893: $this->removeMessageByText($item['message']);
894: }
895: }
896:
897: if (!$this->_errorInfos->getItems()) {
898: $this->_setHasError(false);
899: }
900:
901: return $this;
902: }
903: }
904: