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: class Mage_Catalog_Model_Convert_Parser_Product
29: extends Mage_Eav_Model_Convert_Parser_Abstract
30: {
31: const MULTI_DELIMITER = ' , ';
32: protected $_resource;
33:
34: 35: 36: 37: 38:
39: protected $_collections;
40:
41: 42: 43: 44: 45:
46: protected $_productTypeInstances = array();
47:
48: 49: 50: 51: 52:
53: protected $_productTypes;
54:
55: protected $_inventoryFields = array();
56:
57: protected $_imageFields = array();
58:
59: protected $_systemFields = array();
60: protected $_internalFields = array();
61: protected $_externalFields = array();
62:
63: protected $_inventoryItems = array();
64:
65: protected $_productModel;
66:
67: protected $_setInstances = array();
68:
69: protected $_store;
70: protected $_storeId;
71: protected $_attributes = array();
72:
73: public function __construct()
74: {
75: foreach (Mage::getConfig()->getFieldset('catalog_product_dataflow', 'admin') as $code=>$node) {
76: if ($node->is('inventory')) {
77: $this->_inventoryFields[] = $code;
78: if ($node->is('use_config')) {
79: $this->_inventoryFields[] = 'use_config_'.$code;
80: }
81: }
82: if ($node->is('internal')) {
83: $this->_internalFields[] = $code;
84: }
85: if ($node->is('system')) {
86: $this->_systemFields[] = $code;
87: }
88: if ($node->is('external')) {
89: $this->_externalFields[$code] = $code;
90: }
91: if ($node->is('img')) {
92: $this->_imageFields[] = $code;
93: }
94: }
95: }
96:
97: 98: 99:
100: public function getResource()
101: {
102: if (!$this->_resource) {
103: $this->_resource = Mage::getResourceSingleton('catalog_entity/convert');
104:
105:
106:
107:
108: }
109: return $this->_resource;
110: }
111:
112: public function getCollection($storeId)
113: {
114: if (!isset($this->_collections[$storeId])) {
115: $this->_collections[$storeId] = Mage::getResourceModel('catalog/product_collection');
116: $this->_collections[$storeId]->getEntity()->setStore($storeId);
117: }
118: return $this->_collections[$storeId];
119: }
120:
121: 122: 123: 124: 125:
126: public function getProductTypes()
127: {
128: if (is_null($this->_productTypes)) {
129: $this->_productTypes = Mage::getSingleton('catalog/product_type')
130: ->getOptionArray();
131: }
132: return $this->_productTypes;
133: }
134:
135: 136: 137: 138: 139: 140:
141: public function getProductTypeName($code)
142: {
143: $productTypes = $this->getProductTypes();
144: if (isset($productTypes[$code])) {
145: return $productTypes[$code];
146: }
147: return false;
148: }
149:
150: 151: 152: 153: 154: 155:
156: public function getProductTypeId($name)
157: {
158: $productTypes = $this->getProductTypes();
159: if ($code = array_search($name, $productTypes)) {
160: return $code;
161: }
162: return false;
163: }
164:
165: 166: 167: 168: 169:
170: public function getProductModel()
171: {
172: if (is_null($this->_productModel)) {
173: $productModel = Mage::getModel('catalog/product');
174: $this->_productModel = Mage::objects()->save($productModel);
175: }
176: return Mage::objects()->load($this->_productModel);
177: }
178:
179: 180: 181: 182: 183:
184: public function getStore()
185: {
186: if (is_null($this->_store)) {
187: try {
188: $store = Mage::app()->getStore($this->getVar('store'));
189: } catch (Exception $e) {
190: $this->addException(
191: Mage::helper('catalog')->__('Invalid store specified'),
192: Varien_Convert_Exception::FATAL
193: );
194: throw $e;
195: }
196: $this->_store = $store;
197: }
198: return $this->_store;
199: }
200:
201: 202: 203: 204: 205:
206: public function getStoreId()
207: {
208: if (is_null($this->_storeId)) {
209: $this->_storeId = $this->getStore()->getId();
210: }
211: return $this->_storeId;
212: }
213:
214: 215: 216: 217: 218: 219:
220: public function setProductTypeInstance(Mage_Catalog_Model_Product $product)
221: {
222: $type = $product->getTypeId();
223: if (!isset($this->_productTypeInstances[$type])) {
224: $this->_productTypeInstances[$type] = Mage::getSingleton('catalog/product_type')
225: ->factory($product, true);
226: }
227: $product->setTypeInstance($this->_productTypeInstances[$type], true);
228: return $this;
229: }
230:
231: public function getAttributeSetInstance()
232: {
233: $productType = $this->getProductModel()->getType();
234: $attributeSetId = $this->getProductModel()->getAttributeSetId();
235:
236: if (!isset($this->_setInstances[$productType][$attributeSetId])) {
237: $this->_setInstances[$productType][$attributeSetId] =
238: Mage::getSingleton('catalog/product_type')->factory($this->getProductModel());
239: }
240:
241: return $this->_setInstances[$productType][$attributeSetId];
242: }
243:
244: 245: 246: 247: 248: 249:
250: public function getAttribute($code)
251: {
252: if (!isset($this->_attributes[$code])) {
253: $this->_attributes[$code] = $this->getProductModel()->getResource()->getAttribute($code);
254: }
255: return $this->_attributes[$code];
256: }
257:
258: 259: 260:
261: public function parse()
262: {
263: $data = $this->getData();
264: $entityTypeId = Mage::getSingleton('eav/config')->getEntityType(Mage_Catalog_Model_Product::ENTITY)->getId();
265: $inventoryFields = array();
266:
267: foreach ($data as $i=>$row) {
268: $this->setPosition('Line: '.($i+1));
269: try {
270:
271: if (empty($row['sku'])) {
272: $this->addException(
273: Mage::helper('catalog')->__('Missing SKU, skipping the record.'),
274: Mage_Dataflow_Model_Convert_Exception::ERROR
275: );
276: continue;
277: }
278: $this->setPosition('Line: '.($i+1).', SKU: '.$row['sku']);
279:
280:
281: if (empty($row['entity_id'])) {
282: $row['entity_id'] = $this->getResource()->getProductIdBySku($row['sku']);
283: }
284:
285:
286: if (empty($row['attribute_set'])) {
287: $row['attribute_set'] = 'Default';
288: }
289:
290: $row['attribute_set_id'] = $this->getAttributeSetId($entityTypeId, $row['attribute_set']);
291: if (!$row['attribute_set_id']) {
292: $this->addException(
293: Mage::helper('catalog')->__('Invalid attribute set specified, skipping the record.'),
294: Mage_Dataflow_Model_Convert_Exception::ERROR
295: );
296: continue;
297: }
298:
299: if (empty($row['type'])) {
300: $row['type'] = 'Simple';
301: }
302:
303: $row['type_id'] = $this->getProductTypeId($row['type']);
304: if (!$row['type_id']) {
305: $this->addException(
306: Mage::helper('catalog')->__('Invalid product type specified, skipping the record.'),
307: Mage_Dataflow_Model_Convert_Exception::ERROR
308: );
309: continue;
310: }
311:
312:
313: $storeIds = $this->getStoreIds(isset($row['store']) ? $row['store'] : $this->getVar('store'));
314: if (!$storeIds) {
315: $this->addException(
316: Mage::helper('catalog')->__('Invalid store specified, skipping the record.'),
317: Mage_Dataflow_Model_Convert_Exception::ERROR
318: );
319: continue;
320: }
321:
322:
323: $rowError = false;
324: foreach ($storeIds as $storeId) {
325: $collection = $this->getCollection($storeId);
326: $entity = $collection->getEntity();
327:
328: $model = Mage::getModel('catalog/product');
329: $model->setStoreId($storeId);
330: if (!empty($row['entity_id'])) {
331: $model->load($row['entity_id']);
332: }
333: foreach ($row as $field=>$value) {
334: $attribute = $entity->getAttribute($field);
335:
336: if (!$attribute) {
337:
338:
339: if (in_array($field, $this->_inventoryFields)) {
340: $inventoryFields[$row['sku']][$field] = $value;
341: }
342: continue;
343:
344:
345:
346:
347: }
348: if ($attribute->usesSource()) {
349: $source = $attribute->getSource();
350: $optionId = $this->getSourceOptionId($source, $value);
351: if (is_null($optionId)) {
352: $rowError = true;
353: $this->addException(
354: Mage::helper('catalog')->__('Invalid attribute option specified for attribute %s (%s), skipping the record.', $field, $value),
355: Mage_Dataflow_Model_Convert_Exception::ERROR
356: );
357: continue;
358: }
359: $value = $optionId;
360: }
361: $model->setData($field, $value);
362:
363: }
364:
365:
366:
367: if (!$rowError) {
368: $collection->addItem($model);
369: }
370: unset($model);
371: }
372: } catch (Exception $e) {
373: if (!$e instanceof Mage_Dataflow_Model_Convert_Exception) {
374: $this->addException(
375: Mage::helper('catalog')->__('Error during retrieval of option value: %s', $e->getMessage()),
376: Mage_Dataflow_Model_Convert_Exception::FATAL
377: );
378: }
379: }
380: }
381:
382:
383: if (sizeof($inventoryFields) > 0) {
384: Mage::register('current_imported_inventory', $inventoryFields);
385:
386: }
387:
388: $this->setData($this->_collections);
389: return $this;
390: }
391:
392: public function setInventoryItems($items)
393: {
394: $this->_inventoryItems = $items;
395: }
396:
397: public function getInventoryItems()
398: {
399: return $this->_inventoryItems;
400: }
401:
402: 403: 404: 405: 406:
407: public function unparse()
408: {
409: $entityIds = $this->getData();
410:
411: foreach ($entityIds as $i => $entityId) {
412: $product = $this->getProductModel()
413: ->setStoreId($this->getStoreId())
414: ->load($entityId);
415: $this->setProductTypeInstance($product);
416:
417:
418: $position = Mage::helper('catalog')->__('Line %d, SKU: %s', ($i+1), $product->getSku());
419: $this->setPosition($position);
420:
421: $row = array(
422: 'store' => $this->getStore()->getCode(),
423: 'websites' => '',
424: 'attribute_set' => $this->getAttributeSetName($product->getEntityTypeId(),
425: $product->getAttributeSetId()),
426: 'type' => $product->getTypeId(),
427: 'category_ids' => join(',', $product->getCategoryIds())
428: );
429:
430: if ($this->getStore()->getCode() == Mage_Core_Model_Store::ADMIN_CODE) {
431: $websiteCodes = array();
432: foreach ($product->getWebsiteIds() as $websiteId) {
433: $websiteCode = Mage::app()->getWebsite($websiteId)->getCode();
434: $websiteCodes[$websiteCode] = $websiteCode;
435: }
436: $row['websites'] = join(',', $websiteCodes);
437: } else {
438: $row['websites'] = $this->getStore()->getWebsite()->getCode();
439: if ($this->getVar('url_field')) {
440: $row['url'] = $product->getProductUrl(false);
441: }
442: }
443:
444: foreach ($product->getData() as $field => $value) {
445: if (in_array($field, $this->_systemFields) || is_object($value)) {
446: continue;
447: }
448:
449: $attribute = $this->getAttribute($field);
450: if (!$attribute) {
451: continue;
452: }
453:
454: if ($attribute->usesSource()) {
455: $option = $attribute->getSource()->getOptionText($value);
456: if ($value && empty($option) && $option != '0') {
457: $this->addException(
458: Mage::helper('catalog')->__('Invalid option ID specified for %s (%s), skipping the record.', $field, $value),
459: Mage_Dataflow_Model_Convert_Exception::ERROR
460: );
461: continue;
462: }
463: if (is_array($option)) {
464: $value = join(self::MULTI_DELIMITER, $option);
465: } else {
466: $value = $option;
467: }
468: unset($option);
469: } elseif (is_array($value)) {
470: continue;
471: }
472:
473: $row[$field] = $value;
474: }
475:
476: if ($stockItem = $product->getStockItem()) {
477: foreach ($stockItem->getData() as $field => $value) {
478: if (in_array($field, $this->_systemFields) || is_object($value)) {
479: continue;
480: }
481: $row[$field] = $value;
482: }
483: }
484:
485: foreach ($this->_imageFields as $field) {
486: if (isset($row[$field]) && $row[$field] == 'no_selection') {
487: $row[$field] = null;
488: }
489: }
490:
491: $batchExport = $this->getBatchExportModel()
492: ->setId(null)
493: ->setBatchId($this->getBatchModel()->getId())
494: ->setBatchData($row)
495: ->setStatus(1)
496: ->save();
497: $product->reset();
498: }
499:
500: return $this;
501: }
502:
503: 504: 505: 506: 507:
508: public function getExternalAttributes()
509: {
510: $productAttributes = Mage::getResourceModel('catalog/product_attribute_collection')->load();
511: $attributes = $this->_externalFields;
512:
513: foreach ($productAttributes as $attr) {
514: $code = $attr->getAttributeCode();
515: if (in_array($code, $this->_internalFields) || $attr->getFrontendInput() == 'hidden') {
516: continue;
517: }
518: $attributes[$code] = $code;
519: }
520:
521: foreach ($this->_inventoryFields as $field) {
522: $attributes[$field] = $field;
523: }
524:
525: return $attributes;
526: }
527: }
528: