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_ImportExport_Model_Import_Entity_Product_Type_Configurable
35: extends Mage_ImportExport_Model_Import_Entity_Product_Type_Abstract
36: {
37: 38: 39:
40: const ERROR_ATTRIBUTE_CODE_IS_NOT_SUPER = 'attrCodeIsNotSuper';
41: const ERROR_INVALID_PRICE_CORRECTION = 'invalidPriceCorr';
42: const ERROR_INVALID_OPTION_VALUE = 'invalidOptionValue';
43: const ERROR_INVALID_WEBSITE = 'invalidSuperAttrWebsite';
44:
45: 46: 47: 48: 49:
50: protected $_messageTemplates = array(
51: self::ERROR_ATTRIBUTE_CODE_IS_NOT_SUPER => 'Attribute with this code is not super',
52: self::ERROR_INVALID_PRICE_CORRECTION => 'Super attribute price correction value is invalid',
53: self::ERROR_INVALID_OPTION_VALUE => 'Invalid option value',
54: self::ERROR_INVALID_WEBSITE => 'Invalid website code for super attribute'
55: );
56:
57: 58: 59: 60: 61:
62: protected $_particularAttributes = array(
63: '_super_products_sku', '_super_attribute_code', '_super_attribute_option',
64: '_super_attribute_price_corr', '_super_attribute_price_website'
65: );
66:
67: 68: 69: 70: 71: 72: 73: 74: 75: 76:
77: protected $_productSuperAttrs = array();
78:
79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95:
96: protected $_skuSuperAttributeValues = array();
97:
98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114:
115: protected $_skuSuperData = array();
116:
117: 118: 119: 120: 121:
122: protected $_superAttributes = array();
123:
124: 125: 126: 127: 128:
129: protected $_superAttrValuesCombs = null;
130:
131: 132: 133: 134: 135: 136: 137:
138: protected function _addAttributeParams($attrSetName, array $attrParams)
139: {
140:
141: if ('select' == $attrParams['type'] && 1 == $attrParams['is_global'] && $attrParams['for_configurable']) {
142: $this->_superAttributes[$attrParams['code']] = $attrParams;
143: }
144: return parent::_addAttributeParams($attrSetName, $attrParams);
145: }
146:
147: 148: 149: 150: 151: 152: 153:
154: protected function _getSuperAttributeId($productId, $attributeId)
155: {
156: if (isset($this->_productSuperAttrs["{$productId}_{$attributeId}"])) {
157: return $this->_productSuperAttrs["{$productId}_{$attributeId}"];
158: } else {
159: return null;
160: }
161: }
162:
163: 164: 165: 166: 167: 168:
169: protected function _isAttributeRequiredCheckNeeded($attrCode)
170: {
171: return !$this->_isAttributeSuper($attrCode);
172: }
173:
174: 175: 176: 177: 178: 179:
180: protected function _isAttributeSuper($attrCode)
181: {
182: return isset($this->_superAttributes[$attrCode]);
183: }
184:
185: 186: 187: 188: 189: 190: 191:
192: protected function _isParticularAttributesValid(array $rowData, $rowNum)
193: {
194: if (!empty($rowData['_super_attribute_code'])) {
195: $superAttrCode = $rowData['_super_attribute_code'];
196:
197: if (!$this->_isAttributeSuper($superAttrCode)) {
198: $this->_entityModel->addRowError(self::ERROR_ATTRIBUTE_CODE_IS_NOT_SUPER, $rowNum);
199: return false;
200: } elseif (isset($rowData['_super_attribute_option']) && strlen($rowData['_super_attribute_option'])) {
201: $optionKey = strtolower($rowData['_super_attribute_option']);
202: if (!isset($this->_superAttributes[$superAttrCode]['options'][$optionKey])) {
203: $this->_entityModel->addRowError(self::ERROR_INVALID_OPTION_VALUE, $rowNum);
204: return false;
205: }
206:
207: if (!empty($rowData['_super_attribute_price_corr'])
208: && !$this->_isPriceCorr($rowData['_super_attribute_price_corr'])
209: ) {
210: $this->_entityModel->addRowError(self::ERROR_INVALID_PRICE_CORRECTION, $rowNum);
211: return false;
212: }
213: }
214: }
215: return true;
216: }
217:
218: 219: 220: 221: 222:
223: protected function _loadSkuSuperAttributeValues()
224: {
225: if ($this->_superAttributes) {
226: $attrSetIdToName = $this->_entityModel->getAttrSetIdToName();
227: $allowProductTypes = array();
228:
229: foreach (Mage::getConfig()
230: ->getNode('global/catalog/product/type/configurable/allow_product_types')->children() as $type) {
231: $allowProductTypes[] = $type->getName();
232: }
233: foreach (Mage::getResourceModel('catalog/product_collection')
234: ->addFieldToFilter('type_id', $allowProductTypes)
235: ->addAttributeToSelect(array_keys($this->_superAttributes)) as $product) {
236: $attrSetName = $attrSetIdToName[$product->getAttributeSetId()];
237:
238: $data = array_intersect_key(
239: $product->getData(),
240: $this->_superAttributes
241: );
242: foreach ($data as $attrCode => $value) {
243: $attrId = $this->_superAttributes[$attrCode]['id'];
244: $this->_skuSuperAttributeValues[$attrSetName][$product->getId()][$attrId] = $value;
245: }
246: }
247: }
248: return $this;
249: }
250:
251: 252: 253: 254: 255:
256: protected function _loadSkuSuperData()
257: {
258: if (!$this->_skuSuperData) {
259: $connection = $this->_entityModel->getConnection();
260: $mainTable = Mage::getSingleton('core/resource')->getTableName('catalog/product_super_attribute');
261: $priceTable = Mage::getSingleton('core/resource')->getTableName('catalog/product_super_attribute_pricing');
262: $select = $connection->select()
263: ->from(array('m' => $mainTable), array('product_id', 'attribute_id', 'product_super_attribute_id'))
264: ->joinLeft(
265: array('p' => $priceTable),
266: $connection->quoteIdentifier('p.product_super_attribute_id') . ' = '
267: . $connection->quoteIdentifier('m.product_super_attribute_id'),
268: array('value_index')
269: );
270:
271: foreach ($connection->fetchAll($select) as $row) {
272: $attrId = $row['attribute_id'];
273: $productId = $row['product_id'];
274: if ($row['value_index']) {
275: $this->_skuSuperData[$productId][$attrId][$row['value_index']] = true;
276: }
277: $this->_productSuperAttrs["{$productId}_{$attrId}"] = $row['product_super_attribute_id'];
278: }
279: }
280: return $this;
281: }
282:
283: 284: 285: 286: 287: 288: 289:
290: protected function _processSuperData(array $superData, array &$superAttributes)
291: {
292: if ($superData) {
293: $usedCombs = array();
294:
295: foreach (array_keys($superData['assoc_ids']) as $assocId) {
296: if (!isset($this->_skuSuperAttributeValues[$superData['attr_set_code']][$assocId])) {
297: continue;
298: }
299: if ($superData['used_attributes']) {
300: $skuSuperValues = $this->_skuSuperAttributeValues[$superData['attr_set_code']][$assocId];
301: $usedCombParts = array();
302:
303: foreach ($superData['used_attributes'] as $usedAttrId => $usedValues) {
304: if (empty($skuSuperValues[$usedAttrId]) || !isset($usedValues[$skuSuperValues[$usedAttrId]])) {
305: continue;
306: }
307: $usedCombParts[] = $skuSuperValues[$usedAttrId];
308: $superData['used_attributes'][$usedAttrId][$skuSuperValues[$usedAttrId]] = true;
309: }
310: $comb = implode('|', $usedCombParts);
311:
312: if (isset($usedCombs[$comb])) {
313: continue;
314: }
315: $usedCombs[$comb] = true;
316: }
317: $superAttributes['super_link'][] = array(
318: 'product_id' => $assocId, 'parent_id' => $superData['product_id']
319: );
320: $superAttributes['relation'][] = array(
321: 'parent_id' => $superData['product_id'], 'child_id' => $assocId
322: );
323: }
324:
325: foreach ($superData['used_attributes'] as $usedAttrId => $usedValues) {
326: foreach ($usedValues as $optionId => $isUsed) {
327: if (!$isUsed
328: && isset($superAttributes['pricing'][$superData['product_id']][$usedAttrId])
329: ) {
330: foreach ($superAttributes['pricing'][$superData['product_id']][$usedAttrId] as $k => $params) {
331: if ($optionId == $params['value_index']) {
332: unset($superAttributes['pricing'][$superData['product_id']][$usedAttrId][$k]);
333: }
334: }
335: }
336: }
337: }
338: }
339: return $this;
340: }
341:
342: 343: 344: 345: 346: 347:
348: public function saveData()
349: {
350: $connection = $this->_entityModel->getConnection();
351: $mainTable = Mage::getSingleton('core/resource')->getTableName('catalog/product_super_attribute');
352: $labelTable = Mage::getSingleton('core/resource')->getTableName('catalog/product_super_attribute_label');
353: $priceTable = Mage::getSingleton('core/resource')->getTableName('catalog/product_super_attribute_pricing');
354: $linkTable = Mage::getSingleton('core/resource')->getTableName('catalog/product_super_link');
355: $relationTable = Mage::getSingleton('core/resource')->getTableName('catalog/product_relation');
356: $newSku = $this->_entityModel->getNewSku();
357: $oldSku = $this->_entityModel->getOldSku();
358: $productSuperData = array();
359: $productData = null;
360: $nextAttrId = Mage::getResourceHelper('importexport')->getNextAutoincrement($mainTable);
361:
362: if ($this->_entityModel->getBehavior() == Mage_ImportExport_Model_Import::BEHAVIOR_APPEND) {
363: $this->_loadSkuSuperData();
364: }
365: $this->_loadSkuSuperAttributeValues();
366:
367: while ($bunch = $this->_entityModel->getNextBunch()) {
368: $superAttributes = array(
369: 'attributes' => array(),
370: 'labels' => array(),
371: 'pricing' => array(),
372: 'super_link' => array(),
373: 'relation' => array()
374: );
375: foreach ($bunch as $rowNum => $rowData) {
376: if (!$this->_entityModel->isRowAllowedToImport($rowData, $rowNum)) {
377: continue;
378: }
379:
380: $scope = $this->_entityModel->getRowScope($rowData);
381: if (Mage_ImportExport_Model_Import_Entity_Product::SCOPE_DEFAULT == $scope) {
382: $productData = $newSku[$rowData[Mage_ImportExport_Model_Import_Entity_Product::COL_SKU]];
383:
384: if ($this->_type != $productData['type_id']) {
385: $productData = null;
386: continue;
387: }
388: $productId = $productData['entity_id'];
389:
390: $this->_processSuperData($productSuperData, $superAttributes);
391:
392: $productSuperData = array(
393: 'product_id' => $productId,
394: 'attr_set_code' => $productData['attr_set_code'],
395: 'used_attributes' => empty($this->_skuSuperData[$productId])
396: ? array() : $this->_skuSuperData[$productId],
397: 'assoc_ids' => array()
398: );
399: } elseif (null === $productData) {
400: continue;
401: }
402: if (!empty($rowData['_super_products_sku'])) {
403: if (isset($newSku[$rowData['_super_products_sku']])) {
404: $productSuperData['assoc_ids'][$newSku[$rowData['_super_products_sku']]['entity_id']] = true;
405: } elseif (isset($oldSku[$rowData['_super_products_sku']])) {
406: $productSuperData['assoc_ids'][$oldSku[$rowData['_super_products_sku']]['entity_id']] = true;
407: }
408: }
409: if (empty($rowData['_super_attribute_code'])) {
410: continue;
411: }
412: $attrParams = $this->_superAttributes[$rowData['_super_attribute_code']];
413:
414: if ($this->_getSuperAttributeId($productId, $attrParams['id'])) {
415: $productSuperAttrId = $this->_getSuperAttributeId($productId, $attrParams['id']);
416: } elseif (!isset($superAttributes['attributes'][$productId][$attrParams['id']])) {
417: $productSuperAttrId = $nextAttrId++;
418: $superAttributes['attributes'][$productId][$attrParams['id']] = array(
419: 'product_super_attribute_id' => $productSuperAttrId, 'position' => 0
420: );
421: $superAttributes['labels'][] = array(
422: 'product_super_attribute_id' => $productSuperAttrId,
423: 'store_id' => 0,
424: 'use_default' => 1,
425: 'value' => $attrParams['frontend_label']
426: );
427: }
428: if (isset($rowData['_super_attribute_option']) && strlen($rowData['_super_attribute_option'])) {
429: $optionId = $attrParams['options'][strtolower($rowData['_super_attribute_option'])];
430:
431: if (!isset($productSuperData['used_attributes'][$attrParams['id']][$optionId])) {
432: $productSuperData['used_attributes'][$attrParams['id']][$optionId] = false;
433: }
434: if (!empty($rowData['_super_attribute_price_corr'])) {
435: $superAttributes['pricing'][] = array(
436: 'product_super_attribute_id' => $productSuperAttrId,
437: 'value_index' => $optionId,
438: 'is_percent' => '%' == substr($rowData['_super_attribute_price_corr'], -1),
439: 'pricing_value' => (float) rtrim($rowData['_super_attribute_price_corr'], '%'),
440: 'website_id' => 0
441: );
442: }
443: }
444: }
445:
446: $this->_processSuperData($productSuperData, $superAttributes);
447:
448:
449: if ($this->_entityModel->getBehavior() != Mage_ImportExport_Model_Import::BEHAVIOR_APPEND
450: && $superAttributes['attributes']) {
451: $quoted = $connection->quoteInto('IN (?)', array_keys($superAttributes['attributes']));
452: $connection->delete($mainTable, "product_id {$quoted}");
453: $connection->delete($linkTable, "parent_id {$quoted}");
454: $connection->delete($relationTable, "parent_id {$quoted}");
455: }
456: $mainData = array();
457:
458: foreach ($superAttributes['attributes'] as $productId => $attributesData) {
459: foreach ($attributesData as $attrId => $row) {
460: $row['product_id'] = $productId;
461: $row['attribute_id'] = $attrId;
462: $mainData[] = $row;
463: }
464: }
465: if ($mainData) {
466: $connection->insertOnDuplicate($mainTable, $mainData);
467: }
468: if ($superAttributes['labels']) {
469: $connection->insertOnDuplicate($labelTable, $superAttributes['labels']);
470: }
471: if ($superAttributes['pricing']) {
472: $connection->insertOnDuplicate(
473: $priceTable,
474: $superAttributes['pricing'],
475: array('is_percent', 'pricing_value')
476: );
477: }
478: if ($superAttributes['super_link']) {
479: $connection->insertOnDuplicate($linkTable, $superAttributes['super_link']);
480: }
481: if ($superAttributes['relation']) {
482: $connection->insertOnDuplicate($relationTable, $superAttributes['relation']);
483: }
484: }
485: return $this;
486: }
487: }
488: