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: 36:
37: class Mage_Catalog_Model_Product extends Mage_Catalog_Model_Abstract
38: {
39: 40: 41: 42:
43: const ENTITY = 'catalog_product';
44:
45: const CACHE_TAG = 'catalog_product';
46: protected $_cacheTag = 'catalog_product';
47: protected $_eventPrefix = 'catalog_product';
48: protected $_eventObject = 'product';
49: protected $_canAffectOptions = false;
50:
51: 52: 53: 54: 55:
56: protected $_typeInstance = null;
57:
58: 59: 60:
61: protected $_typeInstanceSingleton = null;
62:
63: 64: 65: 66: 67:
68: protected $_linkInstance;
69:
70: 71: 72: 73: 74:
75: protected $_customOptions = array();
76:
77: 78: 79: 80: 81:
82: protected $_urlModel = null;
83:
84: protected static $_url;
85: protected static $_urlRewrite;
86:
87: protected $_errors = array();
88:
89: protected $_optionInstance;
90:
91: protected $_options = array();
92:
93: 94: 95:
96: protected $_reservedAttributes;
97:
98: 99: 100: 101: 102:
103: protected $_isDuplicable = true;
104:
105: 106: 107: 108: 109:
110: protected $_calculatePrice = true;
111:
112: 113: 114:
115: protected function _construct()
116: {
117: $this->_init('catalog/product');
118: }
119:
120: 121: 122: 123: 124: 125:
126: protected function _initOldFieldsMap()
127: {
128: $this->_oldFieldsMap = Mage::helper('catalog')->getOldFieldMap();
129: return $this;
130: }
131:
132: 133: 134: 135: 136:
137: public function getStoreId()
138: {
139: if ($this->hasData('store_id')) {
140: return $this->getData('store_id');
141: }
142: return Mage::app()->getStore()->getId();
143: }
144:
145: 146: 147: 148: 149:
150: public function getResourceCollection()
151: {
152: if (empty($this->_resourceCollectionName)) {
153: Mage::throwException(Mage::helper('catalog')->__('The model collection resource name is not defined.'));
154: }
155: $collection = Mage::getResourceModel($this->_resourceCollectionName);
156: $collection->setStoreId($this->getStoreId());
157: return $collection;
158: }
159:
160: 161: 162: 163: 164:
165: public function getUrlModel()
166: {
167: if ($this->_urlModel === null) {
168: $this->_urlModel = Mage::getSingleton('catalog/product_url');
169: }
170: return $this->_urlModel;
171: }
172:
173: 174: 175: 176: 177: 178: 179:
180: public function validate()
181: {
182:
183:
184:
185:
186:
187: Mage::dispatchEvent($this->_eventPrefix.'_validate_before', array($this->_eventObject=>$this));
188: $this->_getResource()->validate($this);
189: Mage::dispatchEvent($this->_eventPrefix.'_validate_after', array($this->_eventObject=>$this));
190: return $this;
191: }
192:
193: 194: 195: 196: 197:
198: public function getName()
199: {
200: return $this->_getData('name');
201: }
202:
203: 204: 205: 206: 207:
208: public function getPrice()
209: {
210: if ($this->_calculatePrice || !$this->getData('price')) {
211: return $this->getPriceModel()->getPrice($this);
212: } else {
213: return $this->getData('price');
214: }
215: }
216:
217: 218: 219: 220: 221: 222:
223: public function setPriceCalculation($calculate = true)
224: {
225: $this->_calculatePrice = $calculate;
226: }
227:
228: 229: 230: 231: 232:
233: public function getTypeId()
234: {
235: return $this->_getData('type_id');
236: }
237:
238: 239: 240: 241: 242:
243: public function getStatus()
244: {
245: if (is_null($this->_getData('status'))) {
246: $this->setData('status', Mage_Catalog_Model_Product_Status::STATUS_ENABLED);
247: }
248: return $this->_getData('status');
249: }
250:
251: 252: 253: 254: 255: 256: 257: 258:
259: public function getTypeInstance($singleton = false)
260: {
261: if ($singleton === true) {
262: if (is_null($this->_typeInstanceSingleton)) {
263: $this->_typeInstanceSingleton = Mage::getSingleton('catalog/product_type')
264: ->factory($this, true);
265: }
266: return $this->_typeInstanceSingleton;
267: }
268:
269: if ($this->_typeInstance === null) {
270: $this->_typeInstance = Mage::getSingleton('catalog/product_type')
271: ->factory($this);
272: }
273: return $this->_typeInstance;
274: }
275:
276: 277: 278: 279: 280: 281: 282:
283: public function setTypeInstance($instance, $singleton = false)
284: {
285: if ($singleton === true) {
286: $this->_typeInstanceSingleton = $instance;
287: } else {
288: $this->_typeInstance = $instance;
289: }
290: return $this;
291: }
292:
293: 294: 295: 296: 297:
298: public function getLinkInstance()
299: {
300: if (!$this->_linkInstance) {
301: $this->_linkInstance = Mage::getSingleton('catalog/product_link');
302: }
303: return $this->_linkInstance;
304: }
305:
306: 307: 308: 309: 310: 311:
312: public function getIdBySku($sku)
313: {
314: return $this->_getResource()->getIdBySku($sku);
315: }
316:
317: 318: 319: 320: 321:
322: public function getCategoryId()
323: {
324: if ($category = Mage::registry('current_category')) {
325: return $category->getId();
326: }
327: return false;
328: }
329:
330: 331: 332: 333: 334:
335: public function getCategory()
336: {
337: $category = $this->getData('category');
338: if (is_null($category) && $this->getCategoryId()) {
339: $category = Mage::getModel('catalog/category')->load($this->getCategoryId());
340: $this->setCategory($category);
341: }
342: return $category;
343: }
344:
345: 346: 347: 348: 349: 350:
351: public function setCategoryIds($ids)
352: {
353: if (is_string($ids)) {
354: $ids = explode(',', $ids);
355: } elseif (!is_array($ids)) {
356: Mage::throwException(Mage::helper('catalog')->__('Invalid category IDs.'));
357: }
358: foreach ($ids as $i => $v) {
359: if (empty($v)) {
360: unset($ids[$i]);
361: }
362: }
363:
364: $this->setData('category_ids', $ids);
365: return $this;
366: }
367:
368: 369: 370: 371: 372:
373: public function getCategoryIds()
374: {
375: if (! $this->hasData('category_ids')) {
376: $wasLocked = false;
377: if ($this->isLockedAttribute('category_ids')) {
378: $wasLocked = true;
379: $this->unlockAttribute('category_ids');
380: }
381: $ids = $this->_getResource()->getCategoryIds($this);
382: $this->setData('category_ids', $ids);
383: if ($wasLocked) {
384: $this->lockAttribute('category_ids');
385: }
386: }
387:
388: return (array) $this->_getData('category_ids');
389: }
390:
391: 392: 393: 394: 395:
396: public function getCategoryCollection()
397: {
398: return $this->_getResource()->getCategoryCollection($this);
399: }
400:
401: 402: 403: 404: 405:
406: public function getWebsiteIds()
407: {
408: if (!$this->hasWebsiteIds()) {
409: $ids = $this->_getResource()->getWebsiteIds($this);
410: $this->setWebsiteIds($ids);
411: }
412: return $this->getData('website_ids');
413: }
414:
415: 416: 417: 418: 419:
420: public function getStoreIds()
421: {
422: if (!$this->hasStoreIds()) {
423: $storeIds = array();
424: if ($websiteIds = $this->getWebsiteIds()) {
425: foreach ($websiteIds as $websiteId) {
426: $websiteStores = Mage::app()->getWebsite($websiteId)->getStoreIds();
427: $storeIds = array_merge($storeIds, $websiteStores);
428: }
429: }
430: $this->setStoreIds($storeIds);
431: }
432: return $this->getData('store_ids');
433: }
434:
435: 436: 437: 438: 439: 440: 441: 442:
443: public function getAttributes($groupId = null, $skipSuper = false)
444: {
445: $productAttributes = $this->getTypeInstance(true)->getEditableAttributes($this);
446: if ($groupId) {
447: $attributes = array();
448: foreach ($productAttributes as $attribute) {
449: if ($attribute->isInGroup($this->getAttributeSetId(), $groupId)) {
450: $attributes[] = $attribute;
451: }
452: }
453: } else {
454: $attributes = $productAttributes;
455: }
456:
457: return $attributes;
458: }
459:
460: 461: 462:
463: protected function _beforeSave()
464: {
465: $this->cleanCache();
466: $this->setTypeHasOptions(false);
467: $this->setTypeHasRequiredOptions(false);
468:
469: $this->getTypeInstance(true)->beforeSave($this);
470:
471: $hasOptions = false;
472: $hasRequiredOptions = false;
473:
474: 475: 476: 477: 478:
479: $this->canAffectOptions($this->_canAffectOptions && $this->getCanSaveCustomOptions());
480: if ($this->getCanSaveCustomOptions()) {
481: $options = $this->getProductOptions();
482: if (is_array($options)) {
483: $this->setIsCustomOptionChanged(true);
484: foreach ($this->getProductOptions() as $option) {
485: $this->getOptionInstance()->addOption($option);
486: if ((!isset($option['is_delete'])) || $option['is_delete'] != '1') {
487: $hasOptions = true;
488: }
489: }
490: foreach ($this->getOptionInstance()->getOptions() as $option) {
491: if ($option['is_require'] == '1') {
492: $hasRequiredOptions = true;
493: break;
494: }
495: }
496: }
497: }
498:
499: 500: 501: 502:
503: if ($hasOptions || (bool)$this->getTypeHasOptions()) {
504: $this->setHasOptions(true);
505: if ($hasRequiredOptions || (bool)$this->getTypeHasRequiredOptions()) {
506: $this->setRequiredOptions(true);
507: } elseif ($this->canAffectOptions()) {
508: $this->setRequiredOptions(false);
509: }
510: } elseif ($this->canAffectOptions()) {
511: $this->setHasOptions(false);
512: $this->setRequiredOptions(false);
513: }
514: parent::_beforeSave();
515: }
516:
517: 518: 519: 520: 521: 522: 523:
524: public function canAffectOptions($value = null)
525: {
526: if (null !== $value) {
527: $this->_canAffectOptions = (bool)$value;
528: }
529: return $this->_canAffectOptions;
530: }
531:
532: 533: 534: 535: 536:
537: protected function _afterSave()
538: {
539: $this->getLinkInstance()->saveProductRelations($this);
540: $this->getTypeInstance(true)->save($this);
541:
542: 543: 544:
545: $this->getOptionInstance()->setProduct($this)
546: ->saveOptions();
547:
548: $result = parent::_afterSave();
549:
550: Mage::getSingleton('index/indexer')->processEntityAction(
551: $this, self::ENTITY, Mage_Index_Model_Event::TYPE_SAVE
552: );
553: return $result;
554: }
555:
556: 557: 558: 559: 560: 561:
562: protected function _beforeDelete()
563: {
564: $this->_protectFromNonAdmin();
565: $this->cleanCache();
566: Mage::getSingleton('index/indexer')->logEvent(
567: $this, self::ENTITY, Mage_Index_Model_Event::TYPE_DELETE
568: );
569: return parent::_beforeDelete();
570: }
571:
572: 573: 574: 575: 576:
577: protected function _afterDeleteCommit()
578: {
579: parent::_afterDeleteCommit();
580: Mage::getSingleton('index/indexer')->indexEvents(
581: self::ENTITY, Mage_Index_Model_Event::TYPE_DELETE
582: );
583: }
584:
585: 586: 587: 588: 589:
590: protected function _afterLoad()
591: {
592: parent::_afterLoad();
593: 594: 595:
596: if ($this->getHasOptions()) {
597: foreach ($this->getProductOptionsCollection() as $option) {
598: $option->setProduct($this);
599: $this->addOption($option);
600: }
601: }
602: return $this;
603: }
604:
605: 606: 607: 608: 609:
610: protected function _getResource()
611: {
612: return parent::_getResource();
613: }
614:
615: 616: 617: 618: 619:
620: public function cleanCache()
621: {
622: Mage::app()->cleanCache('catalog_product_'.$this->getId());
623: return $this;
624: }
625:
626: 627: 628: 629: 630:
631: public function getPriceModel()
632: {
633: return Mage::getSingleton('catalog/product_type')->priceFactory($this->getTypeId());
634: }
635:
636: 637: 638: 639: 640:
641: public function getGroupPrice()
642: {
643: return $this->getPriceModel()->getGroupPrice($this);
644: }
645:
646: 647: 648: 649: 650: 651:
652: public function getTierPrice($qty=null)
653: {
654: return $this->getPriceModel()->getTierPrice($qty, $this);
655: }
656:
657: 658: 659: 660: 661:
662: public function getTierPriceCount()
663: {
664: return $this->getPriceModel()->getTierPriceCount($this);
665: }
666:
667: 668: 669: 670: 671: 672:
673: public function getFormatedTierPrice($qty=null)
674: {
675: return $this->getPriceModel()->getFormatedTierPrice($qty, $this);
676: }
677:
678: 679: 680: 681: 682:
683: public function getFormatedPrice()
684: {
685: return $this->getPriceModel()->getFormatedPrice($this);
686: }
687:
688: 689: 690: 691: 692: 693: 694: 695: 696: 697:
698: public function setFinalPrice($price)
699: {
700: $this->_data['final_price'] = $price;
701: return $this;
702: }
703:
704: 705: 706: 707: 708: 709:
710: public function getFinalPrice($qty=null)
711: {
712: $price = $this->_getData('final_price');
713: if ($price !== null) {
714: return $price;
715: }
716: return $this->getPriceModel()->getFinalPrice($qty, $this);
717: }
718:
719: 720: 721: 722: 723:
724: public function getCalculatedFinalPrice()
725: {
726: return $this->_getData('calculated_final_price');
727: }
728:
729: 730: 731: 732: 733:
734: public function getMinimalPrice()
735: {
736: return max($this->_getData('minimal_price'), 0);
737: }
738:
739: 740: 741: 742: 743:
744: public function getSpecialPrice()
745: {
746: return $this->_getData('special_price');
747: }
748:
749: 750: 751: 752: 753:
754: public function getSpecialFromDate()
755: {
756: return $this->_getData('special_from_date');
757: }
758:
759: 760: 761: 762: 763:
764: public function getSpecialToDate()
765: {
766: return $this->_getData('special_to_date');
767: }
768:
769:
770: 771: 772:
773: 774: 775: 776: 777:
778: public function getRelatedProducts()
779: {
780: if (!$this->hasRelatedProducts()) {
781: $products = array();
782: $collection = $this->getRelatedProductCollection();
783: foreach ($collection as $product) {
784: $products[] = $product;
785: }
786: $this->setRelatedProducts($products);
787: }
788: return $this->getData('related_products');
789: }
790:
791: 792: 793: 794: 795:
796: public function getRelatedProductIds()
797: {
798: if (!$this->hasRelatedProductIds()) {
799: $ids = array();
800: foreach ($this->getRelatedProducts() as $product) {
801: $ids[] = $product->getId();
802: }
803: $this->setRelatedProductIds($ids);
804: }
805: return $this->getData('related_product_ids');
806: }
807:
808: 809: 810: 811: 812:
813: public function getRelatedProductCollection()
814: {
815: $collection = $this->getLinkInstance()->useRelatedLinks()
816: ->getProductCollection()
817: ->setIsStrongMode();
818: $collection->setProduct($this);
819: return $collection;
820: }
821:
822: 823: 824: 825: 826:
827: public function getRelatedLinkCollection()
828: {
829: $collection = $this->getLinkInstance()->useRelatedLinks()
830: ->getLinkCollection();
831: $collection->setProduct($this);
832: $collection->addLinkTypeIdFilter();
833: $collection->addProductIdFilter();
834: $collection->joinAttributes();
835: return $collection;
836: }
837:
838: 839: 840: 841: 842:
843: public function getUpSellProducts()
844: {
845: if (!$this->hasUpSellProducts()) {
846: $products = array();
847: foreach ($this->getUpSellProductCollection() as $product) {
848: $products[] = $product;
849: }
850: $this->setUpSellProducts($products);
851: }
852: return $this->getData('up_sell_products');
853: }
854:
855: 856: 857: 858: 859:
860: public function getUpSellProductIds()
861: {
862: if (!$this->hasUpSellProductIds()) {
863: $ids = array();
864: foreach ($this->getUpSellProducts() as $product) {
865: $ids[] = $product->getId();
866: }
867: $this->setUpSellProductIds($ids);
868: }
869: return $this->getData('up_sell_product_ids');
870: }
871:
872: 873: 874: 875: 876:
877: public function getUpSellProductCollection()
878: {
879: $collection = $this->getLinkInstance()->useUpSellLinks()
880: ->getProductCollection()
881: ->setIsStrongMode();
882: $collection->setProduct($this);
883: return $collection;
884: }
885:
886: 887: 888: 889: 890:
891: public function getUpSellLinkCollection()
892: {
893: $collection = $this->getLinkInstance()->useUpSellLinks()
894: ->getLinkCollection();
895: $collection->setProduct($this);
896: $collection->addLinkTypeIdFilter();
897: $collection->addProductIdFilter();
898: $collection->joinAttributes();
899: return $collection;
900: }
901:
902: 903: 904: 905: 906:
907: public function getCrossSellProducts()
908: {
909: if (!$this->hasCrossSellProducts()) {
910: $products = array();
911: foreach ($this->getCrossSellProductCollection() as $product) {
912: $products[] = $product;
913: }
914: $this->setCrossSellProducts($products);
915: }
916: return $this->getData('cross_sell_products');
917: }
918:
919: 920: 921: 922: 923:
924: public function getCrossSellProductIds()
925: {
926: if (!$this->hasCrossSellProductIds()) {
927: $ids = array();
928: foreach ($this->getCrossSellProducts() as $product) {
929: $ids[] = $product->getId();
930: }
931: $this->setCrossSellProductIds($ids);
932: }
933: return $this->getData('cross_sell_product_ids');
934: }
935:
936: 937: 938: 939: 940:
941: public function getCrossSellProductCollection()
942: {
943: $collection = $this->getLinkInstance()->useCrossSellLinks()
944: ->getProductCollection()
945: ->setIsStrongMode();
946: $collection->setProduct($this);
947: return $collection;
948: }
949:
950: 951: 952: 953: 954:
955: public function getCrossSellLinkCollection()
956: {
957: $collection = $this->getLinkInstance()->useCrossSellLinks()
958: ->getLinkCollection();
959: $collection->setProduct($this);
960: $collection->addLinkTypeIdFilter();
961: $collection->addProductIdFilter();
962: $collection->joinAttributes();
963: return $collection;
964: }
965:
966: 967: 968: 969: 970:
971: public function getGroupedLinkCollection()
972: {
973: $collection = $this->getLinkInstance()->useGroupedLinks()
974: ->getLinkCollection();
975: $collection->setProduct($this);
976: $collection->addLinkTypeIdFilter();
977: $collection->addProductIdFilter();
978: $collection->joinAttributes();
979: return $collection;
980: }
981:
982: 983: 984:
985: 986: 987: 988: 989:
990: public function getMediaAttributes()
991: {
992: if (!$this->hasMediaAttributes()) {
993: $mediaAttributes = array();
994: foreach ($this->getAttributes() as $attribute) {
995: if($attribute->getFrontend()->getInputType() == 'media_image') {
996: $mediaAttributes[$attribute->getAttributeCode()] = $attribute;
997: }
998: }
999: $this->setMediaAttributes($mediaAttributes);
1000: }
1001: return $this->getData('media_attributes');
1002: }
1003:
1004: 1005: 1006: 1007: 1008:
1009: public function getMediaGalleryImages()
1010: {
1011: if(!$this->hasData('media_gallery_images') && is_array($this->getMediaGallery('images'))) {
1012: $images = new Varien_Data_Collection();
1013: foreach ($this->getMediaGallery('images') as $image) {
1014: if ($image['disabled']) {
1015: continue;
1016: }
1017: $image['url'] = $this->getMediaConfig()->getMediaUrl($image['file']);
1018: $image['id'] = isset($image['value_id']) ? $image['value_id'] : null;
1019: $image['path'] = $this->getMediaConfig()->getMediaPath($image['file']);
1020: $images->addItem(new Varien_Object($image));
1021: }
1022: $this->setData('media_gallery_images', $images);
1023: }
1024:
1025: return $this->getData('media_gallery_images');
1026: }
1027:
1028: 1029: 1030: 1031: 1032: 1033: 1034: 1035: 1036: 1037:
1038: public function addImageToMediaGallery($file, $mediaAttribute=null, $move=false, $exclude=true)
1039: {
1040: $attributes = $this->getTypeInstance(true)->getSetAttributes($this);
1041: if (!isset($attributes['media_gallery'])) {
1042: return $this;
1043: }
1044: $mediaGalleryAttribute = $attributes['media_gallery'];
1045:
1046: $mediaGalleryAttribute->getBackend()->addImage($this, $file, $mediaAttribute, $move, $exclude);
1047: return $this;
1048: }
1049:
1050: 1051: 1052: 1053: 1054:
1055: public function getMediaConfig()
1056: {
1057: return Mage::getSingleton('catalog/product_media_config');
1058: }
1059:
1060: 1061: 1062: 1063: 1064:
1065: public function duplicate()
1066: {
1067: $this->getWebsiteIds();
1068: $this->getCategoryIds();
1069:
1070:
1071: $newProduct = Mage::getModel('catalog/product')->setData($this->getData())
1072: ->setIsDuplicate(true)
1073: ->setOriginalId($this->getId())
1074: ->setSku(null)
1075: ->setStatus(Mage_Catalog_Model_Product_Status::STATUS_DISABLED)
1076: ->setCreatedAt(null)
1077: ->setUpdatedAt(null)
1078: ->setId(null)
1079: ->setStoreId(Mage::app()->getStore()->getId());
1080:
1081: Mage::dispatchEvent(
1082: 'catalog_model_product_duplicate',
1083: array('current_product' => $this, 'new_product' => $newProduct)
1084: );
1085:
1086:
1087: $data = array();
1088: $this->getLinkInstance()->useRelatedLinks();
1089: $attributes = array();
1090: foreach ($this->getLinkInstance()->getAttributes() as $_attribute) {
1091: if (isset($_attribute['code'])) {
1092: $attributes[] = $_attribute['code'];
1093: }
1094: }
1095: foreach ($this->getRelatedLinkCollection() as $_link) {
1096: $data[$_link->getLinkedProductId()] = $_link->toArray($attributes);
1097: }
1098: $newProduct->setRelatedLinkData($data);
1099:
1100:
1101: $data = array();
1102: $this->getLinkInstance()->useUpSellLinks();
1103: $attributes = array();
1104: foreach ($this->getLinkInstance()->getAttributes() as $_attribute) {
1105: if (isset($_attribute['code'])) {
1106: $attributes[] = $_attribute['code'];
1107: }
1108: }
1109: foreach ($this->getUpSellLinkCollection() as $_link) {
1110: $data[$_link->getLinkedProductId()] = $_link->toArray($attributes);
1111: }
1112: $newProduct->setUpSellLinkData($data);
1113:
1114:
1115: $data = array();
1116: $this->getLinkInstance()->useCrossSellLinks();
1117: $attributes = array();
1118: foreach ($this->getLinkInstance()->getAttributes() as $_attribute) {
1119: if (isset($_attribute['code'])) {
1120: $attributes[] = $_attribute['code'];
1121: }
1122: }
1123: foreach ($this->getCrossSellLinkCollection() as $_link) {
1124: $data[$_link->getLinkedProductId()] = $_link->toArray($attributes);
1125: }
1126: $newProduct->setCrossSellLinkData($data);
1127:
1128:
1129: $data = array();
1130: $this->getLinkInstance()->useGroupedLinks();
1131: $attributes = array();
1132: foreach ($this->getLinkInstance()->getAttributes() as $_attribute) {
1133: if (isset($_attribute['code'])) {
1134: $attributes[] = $_attribute['code'];
1135: }
1136: }
1137: foreach ($this->getGroupedLinkCollection() as $_link) {
1138: $data[$_link->getLinkedProductId()] = $_link->toArray($attributes);
1139: }
1140: $newProduct->setGroupedLinkData($data);
1141:
1142: $newProduct->save();
1143:
1144: $this->getOptionInstance()->duplicate($this->getId(), $newProduct->getId());
1145: $this->getResource()->duplicate($this->getId(), $newProduct->getId());
1146:
1147:
1148: 1149: 1150: 1151: 1152: 1153: 1154: 1155: 1156: 1157: 1158: 1159:
1160: return $newProduct;
1161: }
1162:
1163: 1164: 1165: 1166: 1167:
1168: public function isSuperGroup()
1169: {
1170: return $this->getTypeId() == Mage_Catalog_Model_Product_Type::TYPE_GROUPED;
1171: }
1172:
1173: 1174: 1175: 1176: 1177:
1178: public function isSuperConfig()
1179: {
1180: return $this->isConfigurable();
1181: }
1182: 1183: 1184: 1185: 1186:
1187: public function isGrouped()
1188: {
1189: return $this->getTypeId() == Mage_Catalog_Model_Product_Type::TYPE_GROUPED;
1190: }
1191:
1192: 1193: 1194: 1195: 1196:
1197: public function isConfigurable()
1198: {
1199: return $this->getTypeId() == Mage_Catalog_Model_Product_Type::TYPE_CONFIGURABLE;
1200: }
1201:
1202: 1203: 1204: 1205: 1206:
1207: public function isSuper()
1208: {
1209: return $this->isConfigurable() || $this->isGrouped();
1210: }
1211:
1212: 1213: 1214: 1215: 1216:
1217: public function getVisibleInCatalogStatuses()
1218: {
1219: return Mage::getSingleton('catalog/product_status')->getVisibleStatusIds();
1220: }
1221:
1222: 1223: 1224: 1225: 1226:
1227: public function getVisibleStatuses()
1228: {
1229: return Mage::getSingleton('catalog/product_status')->getVisibleStatusIds();
1230: }
1231:
1232: 1233: 1234: 1235: 1236:
1237: public function isVisibleInCatalog()
1238: {
1239: return in_array($this->getStatus(), $this->getVisibleInCatalogStatuses());
1240: }
1241:
1242: 1243: 1244: 1245: 1246:
1247: public function getVisibleInSiteVisibilities()
1248: {
1249: return Mage::getSingleton('catalog/product_visibility')->getVisibleInSiteIds();
1250: }
1251:
1252: 1253: 1254: 1255: 1256:
1257: public function isVisibleInSiteVisibility()
1258: {
1259: return in_array($this->getVisibility(), $this->getVisibleInSiteVisibilities());
1260: }
1261:
1262: 1263: 1264: 1265: 1266:
1267: public function isDuplicable()
1268: {
1269: return $this->_isDuplicable;
1270: }
1271:
1272: 1273: 1274: 1275: 1276: 1277:
1278: public function setIsDuplicable($value)
1279: {
1280: $this->_isDuplicable = (boolean) $value;
1281: return $this;
1282: }
1283:
1284:
1285: 1286: 1287: 1288: 1289:
1290: public function isSalable()
1291: {
1292: Mage::dispatchEvent('catalog_product_is_salable_before', array(
1293: 'product' => $this
1294: ));
1295:
1296: $salable = $this->isAvailable();
1297:
1298: $object = new Varien_Object(array(
1299: 'product' => $this,
1300: 'is_salable' => $salable
1301: ));
1302: Mage::dispatchEvent('catalog_product_is_salable_after', array(
1303: 'product' => $this,
1304: 'salable' => $object
1305: ));
1306: return $object->getIsSalable();
1307: }
1308:
1309: 1310: 1311: 1312: 1313:
1314: public function isAvailable()
1315: {
1316: return $this->getTypeInstance(true)->isSalable($this)
1317: || Mage::helper('catalog/product')->getSkipSaleableCheck();
1318: }
1319:
1320: 1321: 1322: 1323: 1324:
1325: public function getIsSalable()
1326: {
1327: $productType = $this->getTypeInstance(true);
1328: if (is_callable(array($productType, 'getIsSalable'))) {
1329: return $productType->getIsSalable($this);
1330: }
1331: if ($this->hasData('is_salable')) {
1332: return $this->getData('is_salable');
1333: }
1334:
1335: return $this->isSalable();
1336: }
1337:
1338: 1339: 1340: 1341: 1342: 1343:
1344: public function isVirtual()
1345: {
1346: return $this->getIsVirtual();
1347: }
1348:
1349: 1350: 1351: 1352: 1353:
1354: public function isRecurring()
1355: {
1356: return $this->getIsRecurring() == '1';
1357: }
1358:
1359: 1360: 1361: 1362: 1363:
1364: public function isSaleable()
1365: {
1366: return $this->isSalable();
1367: }
1368:
1369: 1370: 1371: 1372: 1373:
1374: public function isInStock()
1375: {
1376: return $this->getStatus() == Mage_Catalog_Model_Product_Status::STATUS_ENABLED;
1377: }
1378:
1379: 1380: 1381: 1382: 1383: 1384:
1385: public function getAttributeText($attributeCode)
1386: {
1387: return $this->getResource()
1388: ->getAttribute($attributeCode)
1389: ->getSource()
1390: ->getOptionText($this->getData($attributeCode));
1391: }
1392:
1393: 1394: 1395: 1396: 1397:
1398: public function getCustomDesignDate()
1399: {
1400: $result = array();
1401: $result['from'] = $this->getData('custom_design_from');
1402: $result['to'] = $this->getData('custom_design_to');
1403:
1404: return $result;
1405: }
1406:
1407: 1408: 1409: 1410: 1411: 1412:
1413: public function getProductUrl($useSid = null)
1414: {
1415: return $this->getUrlModel()->getProductUrl($this, $useSid);
1416: }
1417:
1418: 1419: 1420: 1421: 1422: 1423:
1424: public function getUrlInStore($params = array())
1425: {
1426: return $this->getUrlModel()->getUrlInStore($this, $params);
1427: }
1428:
1429: 1430: 1431: 1432: 1433: 1434:
1435: public function formatUrlKey($str)
1436: {
1437: return $this->getUrlModel()->formatUrlKey($str);
1438: }
1439:
1440: 1441: 1442: 1443: 1444: 1445:
1446: public function getUrlPath($category=null)
1447: {
1448: return $this->getUrlModel()->getUrlPath($this, $category);
1449: }
1450:
1451: 1452: 1453: 1454: 1455: 1456: 1457: 1458:
1459: public function addAttributeUpdate($code, $value, $store)
1460: {
1461: $oldValue = $this->getData($code);
1462: $oldStore = $this->getStoreId();
1463:
1464: $this->setData($code, $value);
1465: $this->setStoreId($store);
1466: $this->getResource()->saveAttribute($this, $code);
1467:
1468: $this->setData($code, $oldValue);
1469: $this->setStoreId($oldStore);
1470: }
1471:
1472: 1473: 1474: 1475: 1476: 1477:
1478: public function toArray(array $arrAttributes=array())
1479: {
1480: $data = parent::toArray($arrAttributes);
1481: if ($stock = $this->getStockItem()) {
1482: $data['stock_item'] = $stock->toArray();
1483: }
1484: unset($data['stock_item']['product']);
1485: return $data;
1486: }
1487:
1488: 1489: 1490: 1491: 1492: 1493:
1494: public function fromArray($data)
1495: {
1496: if (isset($data['stock_item'])) {
1497: if (Mage::helper('catalog')->isModuleEnabled('Mage_CatalogInventory')) {
1498: $stockItem = Mage::getModel('cataloginventory/stock_item')
1499: ->setData($data['stock_item'])
1500: ->setProduct($this);
1501: $this->setStockItem($stockItem);
1502: }
1503: unset($data['stock_item']);
1504: }
1505: $this->setData($data);
1506: return $this;
1507: }
1508:
1509: 1510: 1511: 1512:
1513: public function loadParentProductIds()
1514: {
1515: return $this->setParentProductIds(array());
1516: }
1517:
1518: 1519: 1520: 1521: 1522:
1523: public function delete()
1524: {
1525: parent::delete();
1526: Mage::dispatchEvent($this->_eventPrefix.'_delete_after_done', array($this->_eventObject=>$this));
1527: return $this;
1528: }
1529:
1530: 1531: 1532: 1533: 1534:
1535: public function getRequestPath()
1536: {
1537: return $this->_getData('request_path');
1538: }
1539:
1540: 1541: 1542: 1543:
1544:
1545: public function getGiftMessageAvailable()
1546: {
1547: return $this->_getData('gift_message_available');
1548: }
1549:
1550: 1551: 1552: 1553: 1554:
1555: public function getRatingSummary()
1556: {
1557: return $this->_getData('rating_summary');
1558: }
1559:
1560: 1561: 1562: 1563: 1564:
1565: public function isComposite()
1566: {
1567: return $this->getTypeInstance(true)->isComposite($this);
1568: }
1569:
1570: 1571: 1572: 1573: 1574:
1575: public function canConfigure()
1576: {
1577: $options = $this->getOptions();
1578: return !empty($options) || $this->getTypeInstance(true)->canConfigure($this);
1579: }
1580:
1581: 1582: 1583: 1584: 1585:
1586: public function getSku()
1587: {
1588: return $this->getTypeInstance(true)->getSku($this);
1589: }
1590:
1591: 1592: 1593: 1594: 1595:
1596: public function getWeight()
1597: {
1598: return $this->getTypeInstance(true)->getWeight($this);
1599: }
1600:
1601: 1602: 1603: 1604: 1605:
1606: public function getOptionInstance()
1607: {
1608: if (!$this->_optionInstance) {
1609: $this->_optionInstance = Mage::getSingleton('catalog/product_option');
1610: }
1611: return $this->_optionInstance;
1612: }
1613:
1614: 1615: 1616: 1617: 1618:
1619: public function getProductOptionsCollection()
1620: {
1621: $collection = $this->getOptionInstance()
1622: ->getProductOptionCollection($this);
1623:
1624: return $collection;
1625: }
1626:
1627: 1628: 1629: 1630: 1631: 1632:
1633: public function addOption(Mage_Catalog_Model_Product_Option $option)
1634: {
1635: $this->_options[$option->getId()] = $option;
1636: return $this;
1637: }
1638:
1639: 1640: 1641: 1642: 1643: 1644:
1645: public function getOptionById($optionId)
1646: {
1647: if (isset($this->_options[$optionId])) {
1648: return $this->_options[$optionId];
1649: }
1650:
1651: return null;
1652: }
1653:
1654: 1655: 1656: 1657: 1658:
1659: public function getOptions()
1660: {
1661: return $this->_options;
1662: }
1663:
1664: 1665: 1666: 1667: 1668:
1669: public function getIsVirtual()
1670: {
1671: return $this->getTypeInstance(true)->isVirtual($this);
1672: }
1673:
1674: 1675: 1676: 1677: 1678: 1679: 1680: 1681:
1682: public function addCustomOption($code, $value, $product=null)
1683: {
1684: $product = $product ? $product : $this;
1685: $option = Mage::getModel('catalog/product_configuration_item_option')
1686: ->addData(array(
1687: 'product_id'=> $product->getId(),
1688: 'product' => $product,
1689: 'code' => $code,
1690: 'value' => $value,
1691: ));
1692: $this->_customOptions[$code] = $option;
1693: return $this;
1694: }
1695:
1696: 1697: 1698: 1699: 1700: 1701:
1702: public function setCustomOptions(array $options)
1703: {
1704: $this->_customOptions = $options;
1705: }
1706:
1707: 1708: 1709: 1710: 1711:
1712: public function getCustomOptions()
1713: {
1714: return $this->_customOptions;
1715: }
1716:
1717: 1718: 1719: 1720: 1721: 1722:
1723: public function getCustomOption($code)
1724: {
1725: if (isset($this->_customOptions[$code])) {
1726: return $this->_customOptions[$code];
1727: }
1728: return null;
1729: }
1730:
1731: 1732: 1733: 1734: 1735:
1736: public function hasCustomOptions()
1737: {
1738: if (count($this->_customOptions)) {
1739: return true;
1740: } else {
1741: return false;
1742: }
1743: }
1744:
1745: 1746: 1747: 1748: 1749: 1750:
1751: public function canBeShowInCategory($categoryId)
1752: {
1753: return $this->_getResource()->canBeShowInCategory($this, $categoryId);
1754: }
1755:
1756: 1757: 1758: 1759: 1760:
1761: public function getAvailableInCategories()
1762: {
1763: return $this->_getResource()->getAvailableInCategories($this);
1764: }
1765:
1766: 1767: 1768: 1769: 1770:
1771: public function getDefaultAttributeSetId()
1772: {
1773: return $this->getResource()->getEntityType()->getDefaultAttributeSetId();
1774: }
1775:
1776: 1777: 1778: 1779: 1780:
1781: protected function _getImageHelper()
1782: {
1783: return Mage::helper('catalog/image');
1784: }
1785:
1786: 1787: 1788: 1789: 1790: 1791:
1792: public function getImageUrl()
1793: {
1794: return (string)$this->_getImageHelper()->init($this, 'image')->resize(265);
1795: }
1796:
1797: 1798: 1799: 1800: 1801: 1802: 1803: 1804:
1805: public function getSmallImageUrl($width = 88, $height = 77)
1806: {
1807: return (string)$this->_getImageHelper()->init($this, 'small_image')->resize($width, $height);
1808: }
1809:
1810: 1811: 1812: 1813: 1814: 1815: 1816: 1817:
1818: public function getThumbnailUrl($width = 75, $height = 75)
1819: {
1820: return (string)$this->_getImageHelper()->init($this, 'thumbnail')->resize($width, $height);
1821: }
1822:
1823: 1824: 1825: 1826: 1827:
1828: public function getReservedAttributes()
1829: {
1830: if ($this->_reservedAttributes === null) {
1831: $_reserved = array('position');
1832: $methods = get_class_methods(__CLASS__);
1833: foreach ($methods as $method) {
1834: if (preg_match('/^get([A-Z]{1}.+)/', $method, $matches)) {
1835: $method = $matches[1];
1836: $tmp = strtolower(preg_replace('/(.)([A-Z])/', "$1_$2", $method));
1837: $_reserved[] = $tmp;
1838: }
1839: }
1840: $_allowed = array(
1841: 'type_id','calculated_final_price','request_path','rating_summary'
1842: );
1843: $this->_reservedAttributes = array_diff($_reserved, $_allowed);
1844: }
1845: return $this->_reservedAttributes;
1846: }
1847:
1848: 1849: 1850: 1851: 1852: 1853:
1854: public function isReservedAttribute ($attribute)
1855: {
1856: return $attribute->getIsUserDefined()
1857: && in_array($attribute->getAttributeCode(), $this->getReservedAttributes());
1858: }
1859:
1860: 1861: 1862: 1863: 1864: 1865: 1866:
1867: public function setOrigData($key=null, $data=null)
1868: {
1869: if (Mage::app()->getStore()->isAdmin()) {
1870: return parent::setOrigData($key, $data);
1871: }
1872:
1873: return $this;
1874: }
1875:
1876: 1877: 1878: 1879: 1880:
1881: public function reset()
1882: {
1883: $this->unlockAttributes();
1884: $this->_clearData();
1885: return $this;
1886: }
1887:
1888: 1889: 1890: 1891: 1892:
1893: public function getCacheIdTags()
1894: {
1895: $tags = parent::getCacheIdTags();
1896: $affectedCategoryIds = $this->getAffectedCategoryIds();
1897: if (!$affectedCategoryIds) {
1898: $affectedCategoryIds = $this->getCategoryIds();
1899: }
1900: foreach ($affectedCategoryIds as $categoryId) {
1901: $tags[] = Mage_Catalog_Model_Category::CACHE_TAG.'_'.$categoryId;
1902: }
1903: return $tags;
1904: }
1905:
1906: 1907: 1908: 1909: 1910: 1911:
1912: public function isProductsHasSku(array $productIds)
1913: {
1914: $products = $this->_getResource()->getProductsSku($productIds);
1915: if (count($products)) {
1916: foreach ($products as $product) {
1917: if (empty($product['sku'])) {
1918: return false;
1919: }
1920: }
1921: return true;
1922: }
1923: return null;
1924: }
1925:
1926: 1927: 1928: 1929: 1930: 1931:
1932: public function processBuyRequest(Varien_Object $buyRequest)
1933: {
1934: $options = new Varien_Object();
1935:
1936:
1937: $customOptions = $buyRequest->getOptions();
1938: if (is_array($customOptions)) {
1939: $options->setOptions(array_diff($buyRequest->getOptions(), array('')));
1940: }
1941:
1942:
1943: $type = $this->getTypeInstance(true);
1944: $typeSpecificOptions = $type->processBuyRequest($this, $buyRequest);
1945: $options->addData($typeSpecificOptions);
1946:
1947:
1948: $options->setErrors($type->checkProductConfiguration($this, $buyRequest));
1949:
1950: return $options;
1951: }
1952:
1953: 1954: 1955: 1956: 1957:
1958: public function getPreconfiguredValues()
1959: {
1960: $preconfiguredValues = $this->getData('preconfigured_values');
1961: if (!$preconfiguredValues) {
1962: $preconfiguredValues = new Varien_Object();
1963: }
1964:
1965: return $preconfiguredValues;
1966: }
1967:
1968: 1969: 1970: 1971: 1972: 1973:
1974: public function prepareCustomOptions()
1975: {
1976: foreach ($this->getCustomOptions() as $option) {
1977: if (!is_object($option->getProduct()) || $option->getId()) {
1978: $this->addCustomOption($option->getCode(), $option->getValue());
1979: }
1980: }
1981:
1982: return $this;
1983: }
1984:
1985: 1986: 1987: 1988: 1989:
1990: protected function _clearReferences()
1991: {
1992: $this->_clearOptionReferences();
1993: return $this;
1994: }
1995:
1996: 1997: 1998: 1999: 2000:
2001: protected function _clearData()
2002: {
2003: foreach ($this->_data as $data){
2004: if (is_object($data) && method_exists($data, 'reset')){
2005: $data->reset();
2006: }
2007: }
2008:
2009: $this->setData(array());
2010: $this->setOrigData();
2011: $this->_customOptions = array();
2012: $this->_optionInstance = null;
2013: $this->_options = array();
2014: $this->_canAffectOptions = false;
2015: $this->_errors = array();
2016:
2017: return $this;
2018: }
2019:
2020: 2021: 2022: 2023: 2024:
2025: protected function _clearOptionReferences()
2026: {
2027: 2028: 2029:
2030: if (!empty($this->_options)) {
2031: foreach ($this->_options as $key => $option) {
2032: $option->setProduct();
2033: $option->clearInstance();
2034: }
2035: }
2036:
2037: return $this;
2038: }
2039:
2040: 2041: 2042: 2043: 2044: 2045:
2046: public function getProductEntitiesInfo($columns = null)
2047: {
2048: return $this->_getResource()->getProductEntitiesInfo($columns);
2049: }
2050:
2051: 2052: 2053: 2054: 2055:
2056: public function isDisabled()
2057: {
2058: return $this->getStatus() == Mage_Catalog_Model_Product_Status::STATUS_DISABLED;
2059: }
2060: }
2061: