From 7f0799f310e1eed1013f0b7b18120d8f26344e2d Mon Sep 17 00:00:00 2001 From: Jim Date: Tue, 18 Dec 2012 18:45:42 -0500 Subject: [PATCH 1/6] Adds the option to choose on which of the available attributes you want to base your configurable product. For example if you had a product that has size & colour as available configurable attributes and you just wanted to base your related simple products on the colour you would add one (or more) configurable attributes to the additional_attributes like this : 'additional_attributes' => array( array( 'key' => 'config_attributes', 'value' => 'some_attribute_code' ) ), --- .../JR/Api/Helper/Catalog/Product.php | 31 ++++++++++++++++--- .../JR/Api/Model/Catalog/Product/Api/V2.php | 10 +++++- app/code/community/JR/Api/etc/wsdl.xml | 1 + app/code/community/JR/Api/etc/wsi.xml | 1 + 4 files changed, 37 insertions(+), 6 deletions(-) diff --git a/app/code/community/JR/Api/Helper/Catalog/Product.php b/app/code/community/JR/Api/Helper/Catalog/Product.php index 6153a6a..1a77157 100644 --- a/app/code/community/JR/Api/Helper/Catalog/Product.php +++ b/app/code/community/JR/Api/Helper/Catalog/Product.php @@ -10,7 +10,7 @@ class JR_Api_Helper_Catalog_Product extends Mage_Core_Helper_Abstract * @param array $priceChanges * @return JR_Api_Helper_Catalog_Product */ - public function associateProducts(Mage_Catalog_Model_Product $product, $simpleSkus, $priceChanges = array()) + public function associateProducts(Mage_Catalog_Model_Product $product, $simpleSkus, $priceChanges = array(), $configAttributes = array()) { if (!empty($simpleSkus)) { $usedProductIds = Mage::getModel('catalog/product')->getCollection() @@ -19,7 +19,7 @@ public function associateProducts(Mage_Catalog_Model_Product $product, $simpleSk ->getAllIds(); if (!empty($usedProductIds)) { if ($product->isConfigurable()) { - $this->_initConfigurableAttributesData($product, $usedProductIds, $priceChanges); + $this->_initConfigurableAttributesData($product, $usedProductIds, $priceChanges, $configAttributes); } elseif ($product->isGrouped()) { $relations = array_fill_keys($usedProductIds, array('qty' => 0, 'position' => 0)); $product->setGroupedLinkData($relations); @@ -102,7 +102,7 @@ protected function _getCatagoriesSeparator() * @param array $priceChanges * @return JR_Api_Helper_Catalog_Product */ - protected function _initConfigurableAttributesData(Mage_Catalog_Model_Product $mainProduct, $simpleProductIds, $priceChanges = array()) + protected function _initConfigurableAttributesData(Mage_Catalog_Model_Product $mainProduct, $simpleProductIds, $priceChanges = array(), $configAttributes = array()) { if (!$mainProduct->isConfigurable() || empty($simpleProductIds)) { return $this; @@ -111,8 +111,19 @@ protected function _initConfigurableAttributesData(Mage_Catalog_Model_Product $m $mainProduct->setConfigurableProductsData(array_flip($simpleProductIds)); $productType = $mainProduct->getTypeInstance(true); $productType->setProduct($mainProduct); - $attributesData = $productType->getConfigurableAttributesAsArray(); + if(!empty($configAttributes)) { + $attributeIds = array(); + foreach ($productType->getSetAttributes() as $attribute) { + if ($productType->canUseAttribute($attribute) && in_array($attribute->getAttributeCode(), $configAttributes)) { + $attributeIds[] = $attribute->getAttributeId(); + } + } + $productType->setUsedProductAttributeIds($attributeIds); + $attributesData = $productType->getConfigurableAttributesAsArray(); + } else { + $attributesData = $productType->getConfigurableAttributesAsArray(); + } if (empty($attributesData)) { // Auto generation if configurable product has no attribute $attributeIds = array(); @@ -157,7 +168,17 @@ protected function _initConfigurableAttributesData(Mage_Catalog_Model_Product $m ); } } - $mainProduct->setConfigurableAttributesData($attributesData); + + if($mainProduct->isObjectNew()) { + + if($mainProduct->isConfigurable()) { + $log_file = "/home/sourismi/magento_app/log/soap.log"; + file_put_contents($log_file, print_r(array('getSku' => $mainProduct->getSku()), true)); + file_put_contents($log_file, print_r(array('attributesData' => $attributesData), true), FILE_APPEND); + } + + $mainProduct->setConfigurableAttributesData($attributesData); + } } return $this; diff --git a/app/code/community/JR/Api/Model/Catalog/Product/Api/V2.php b/app/code/community/JR/Api/Model/Catalog/Product/Api/V2.php index 423b7cb..4b22356 100644 --- a/app/code/community/JR/Api/Model/Catalog/Product/Api/V2.php +++ b/app/code/community/JR/Api/Model/Catalog/Product/Api/V2.php @@ -16,6 +16,8 @@ protected function _prepareDataForSave($product, $productData) { /* @var $product Mage_Catalog_Model_Product */ + $configAttributes = array(); + if (property_exists($productData, 'categories')) { $categoryIds = Mage::helper('jr_api/catalog_product') ->getCategoryIdsByNames((array) $productData->categories); @@ -27,6 +29,12 @@ protected function _prepareDataForSave($product, $productData) if (property_exists($productData, 'additional_attributes')) { $singleDataExists = property_exists((object) $productData->additional_attributes, 'single_data'); $multiDataExists = property_exists((object) $productData->additional_attributes, 'multi_data'); + + $configAttributesExists = property_exists((object) $productData->additional_attributes, 'config_attributes'); + if ($configAttributesExists) { + $configAttributes = explode(',', $productData->additional_attributes['config_attributes']); + } + if ($singleDataExists || $multiDataExists) { if ($singleDataExists) { foreach ($productData->additional_attributes->single_data as $_attribute) { @@ -77,7 +85,7 @@ protected function _prepareDataForSave($product, $productData) $priceChanges = $productData->price_changes; } } - Mage::helper('jr_api/catalog_product')->associateProducts($product, $simpleSkus, $priceChanges); + Mage::helper('jr_api/catalog_product')->associateProducts($product, $simpleSkus, $priceChanges, $configAttributes); } } } diff --git a/app/code/community/JR/Api/etc/wsdl.xml b/app/code/community/JR/Api/etc/wsdl.xml index 04426a1..4ad86aa 100644 --- a/app/code/community/JR/Api/etc/wsdl.xml +++ b/app/code/community/JR/Api/etc/wsdl.xml @@ -9,6 +9,7 @@ + diff --git a/app/code/community/JR/Api/etc/wsi.xml b/app/code/community/JR/Api/etc/wsi.xml index 0447cdd..87e7c13 100644 --- a/app/code/community/JR/Api/etc/wsi.xml +++ b/app/code/community/JR/Api/etc/wsi.xml @@ -22,6 +22,7 @@ + From 36f8a147b83f2a7040a0cb5a65591219868504ea Mon Sep 17 00:00:00 2001 From: Jim Date: Tue, 18 Dec 2012 19:03:43 -0500 Subject: [PATCH 2/6] Removed some debugging cruft --- app/code/community/JR/Api/Helper/Catalog/Product.php | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/app/code/community/JR/Api/Helper/Catalog/Product.php b/app/code/community/JR/Api/Helper/Catalog/Product.php index 1a77157..8ab845c 100644 --- a/app/code/community/JR/Api/Helper/Catalog/Product.php +++ b/app/code/community/JR/Api/Helper/Catalog/Product.php @@ -168,17 +168,6 @@ protected function _initConfigurableAttributesData(Mage_Catalog_Model_Product $m ); } } - - if($mainProduct->isObjectNew()) { - - if($mainProduct->isConfigurable()) { - $log_file = "/home/sourismi/magento_app/log/soap.log"; - file_put_contents($log_file, print_r(array('getSku' => $mainProduct->getSku()), true)); - file_put_contents($log_file, print_r(array('attributesData' => $attributesData), true), FILE_APPEND); - } - - $mainProduct->setConfigurableAttributesData($attributesData); - } } return $this; From 0092d77ee51f5af1d143b7123e02a6b46325b7c8 Mon Sep 17 00:00:00 2001 From: Jim Date: Thu, 20 Dec 2012 12:52:34 -0500 Subject: [PATCH 3/6] Okay that was pretty dumb... --- app/code/community/JR/Api/Helper/Catalog/Product.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/code/community/JR/Api/Helper/Catalog/Product.php b/app/code/community/JR/Api/Helper/Catalog/Product.php index 8ab845c..29be149 100644 --- a/app/code/community/JR/Api/Helper/Catalog/Product.php +++ b/app/code/community/JR/Api/Helper/Catalog/Product.php @@ -168,6 +168,8 @@ protected function _initConfigurableAttributesData(Mage_Catalog_Model_Product $m ); } } + + $mainProduct->setConfigurableAttributesData($attributesData); } return $this; From 16ce081e242aa6fdd9fcb235ebaee81d43885d36 Mon Sep 17 00:00:00 2001 From: Jim Date: Thu, 20 Dec 2012 18:05:28 -0500 Subject: [PATCH 4/6] Remove related products so we don't try to link products which are already linked to the configurable product. (which throws a unique key error) --- .../community/JR/Api/Helper/Catalog/Product.php | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/app/code/community/JR/Api/Helper/Catalog/Product.php b/app/code/community/JR/Api/Helper/Catalog/Product.php index 29be149..f9cc6ae 100644 --- a/app/code/community/JR/Api/Helper/Catalog/Product.php +++ b/app/code/community/JR/Api/Helper/Catalog/Product.php @@ -17,6 +17,23 @@ public function associateProducts(Mage_Catalog_Model_Product $product, $simpleSk ->addFieldToFilter('sku', array('in' => (array) $simpleSkus)) ->addFieldToFilter('type_id', Mage_Catalog_Model_Product_Type::TYPE_SIMPLE) ->getAllIds(); + + + // Remove related products so we don't try to link products which are already linked + $related_products = array(); + $conf = Mage::getModel('catalog/product_type_configurable')->setProduct($product); + $col = $conf->getUsedProductCollection()->addAttributeToSelect('*')->addFilterByRequiredOptions(); + foreach($col as $simple_product){ + $related_products[] = $simple_product->getId(); + } + + for ($i = 0; $i < count($usedProductIds); $i++) { + if(in_array($usedProductIds[$i], $related_products)) { + unset($usedProductIds[$i]); + } + } + + if (!empty($usedProductIds)) { if ($product->isConfigurable()) { $this->_initConfigurableAttributesData($product, $usedProductIds, $priceChanges, $configAttributes); From d4a08af7ad320c967bcbdeb5c2eeef076a4fa68e Mon Sep 17 00:00:00 2001 From: Jim Date: Tue, 12 Feb 2013 17:38:55 -0500 Subject: [PATCH 5/6] Reversed this behaviour we need to include used product IDs so they don't go instead of removing those which are already there. --- .../JR/Api/Helper/Catalog/Product.php | 27 ++++++++----------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/app/code/community/JR/Api/Helper/Catalog/Product.php b/app/code/community/JR/Api/Helper/Catalog/Product.php index f9cc6ae..ec08d35 100644 --- a/app/code/community/JR/Api/Helper/Catalog/Product.php +++ b/app/code/community/JR/Api/Helper/Catalog/Product.php @@ -13,26 +13,21 @@ class JR_Api_Helper_Catalog_Product extends Mage_Core_Helper_Abstract public function associateProducts(Mage_Catalog_Model_Product $product, $simpleSkus, $priceChanges = array(), $configAttributes = array()) { if (!empty($simpleSkus)) { - $usedProductIds = Mage::getModel('catalog/product')->getCollection() + + // Get current associations + $usedProductIds = Mage::getModel('catalog/product_type_configurable')->setProduct($product)->getUsedProductCollection() + ->addAttributeToSelect('*') + ->addFilterByRequiredOptions() + ->getAllIds(); + + // Get new associations + $newProductIds = Mage::getModel('catalog/product')->getCollection() ->addFieldToFilter('sku', array('in' => (array) $simpleSkus)) ->addFieldToFilter('type_id', Mage_Catalog_Model_Product_Type::TYPE_SIMPLE) ->getAllIds(); - - // Remove related products so we don't try to link products which are already linked - $related_products = array(); - $conf = Mage::getModel('catalog/product_type_configurable')->setProduct($product); - $col = $conf->getUsedProductCollection()->addAttributeToSelect('*')->addFilterByRequiredOptions(); - foreach($col as $simple_product){ - $related_products[] = $simple_product->getId(); - } - - for ($i = 0; $i < count($usedProductIds); $i++) { - if(in_array($usedProductIds[$i], $related_products)) { - unset($usedProductIds[$i]); - } - } - + // Combine new and current associations + $usedProductIds = array_unique(array_merge($usedProductIds, $newProductIds)); if (!empty($usedProductIds)) { if ($product->isConfigurable()) { From ca933dcbad47a0afba18646e2d5b83d73c87b8a8 Mon Sep 17 00:00:00 2001 From: Jim Date: Thu, 28 Feb 2013 23:58:38 -0500 Subject: [PATCH 6/6] Added a 'repair' feature for the configurable products. If the product already exists with a different configurable attribute set, de product will be dropped and recreated. It works for me, use at your own risks! --- .../JR/Api/Helper/Catalog/Product.php | 55 ++++++++++--------- .../JR/Api/Model/Catalog/Product/Api/V2.php | 42 ++++++++++++++ 2 files changed, 70 insertions(+), 27 deletions(-) diff --git a/app/code/community/JR/Api/Helper/Catalog/Product.php b/app/code/community/JR/Api/Helper/Catalog/Product.php index ec08d35..0f96f3f 100644 --- a/app/code/community/JR/Api/Helper/Catalog/Product.php +++ b/app/code/community/JR/Api/Helper/Catalog/Product.php @@ -119,38 +119,35 @@ protected function _initConfigurableAttributesData(Mage_Catalog_Model_Product $m if (!$mainProduct->isConfigurable() || empty($simpleProductIds)) { return $this; } - + $mainProduct->setConfigurableProductsData(array_flip($simpleProductIds)); + $productType = $mainProduct->getTypeInstance(true); $productType->setProduct($mainProduct); - - if(!empty($configAttributes)) { - $attributeIds = array(); - foreach ($productType->getSetAttributes() as $attribute) { - if ($productType->canUseAttribute($attribute) && in_array($attribute->getAttributeCode(), $configAttributes)) { - $attributeIds[] = $attribute->getAttributeId(); - } - } - $productType->setUsedProductAttributeIds($attributeIds); - $attributesData = $productType->getConfigurableAttributesAsArray(); - } else { - $attributesData = $productType->getConfigurableAttributesAsArray(); + + // Get attributes already associated to this product + $used_attr_codes = array(); + foreach($productType->getConfigurableAttributesAsArray($mainProduct) as $attr){ + $used_attr_codes[] = $attr['attribute_code']; } - if (empty($attributesData)) { - // Auto generation if configurable product has no attribute - $attributeIds = array(); - foreach ($productType->getSetAttributes() as $attribute) { - if ($productType->canUseAttribute($attribute)) { - $attributeIds[] = $attribute->getAttributeId(); - } + + // Add only the new attributes to this product + $new_attr_ids = array(); + foreach($productType->getSetAttributes() as $attribute) { + if($productType->canUseAttribute($attribute)) { + if(!empty($configAttributes) && + in_array($attribute->getAttributeCode(), $configAttributes) && + !in_array($attribute->getAttributeCode(), $used_attr_codes)) { + + $new_attr_ids[] = $attribute->getAttributeId(); + } } - $productType->setUsedProductAttributeIds($attributeIds); - $attributesData = $productType->getConfigurableAttributesAsArray(); } - - $products = Mage::getModel('catalog/product')->getCollection() - ->addIdFilter($simpleProductIds); - + $productType->setUsedProductAttributeIds($new_attr_ids); + $attributesData = $productType->getConfigurableAttributesAsArray(); + + // Update 'association' attributes + $products = Mage::getModel('catalog/product')->getCollection()->addIdFilter($simpleProductIds); if (count($products)) { foreach ($attributesData as &$attribute) { $attribute['label'] = $attribute['frontend_label']; @@ -183,7 +180,11 @@ protected function _initConfigurableAttributesData(Mage_Catalog_Model_Product $m $mainProduct->setConfigurableAttributesData($attributesData); } - + // + // $log_file = "/home/sourismini/magento_app/prod/var/log/soap.log"; + // $log = print_r(array_flip($simpleProductIds), true); + // file_put_contents($log_file, $log, FILE_APPEND); + // return $this; } } \ No newline at end of file diff --git a/app/code/community/JR/Api/Model/Catalog/Product/Api/V2.php b/app/code/community/JR/Api/Model/Catalog/Product/Api/V2.php index 4b22356..de7d988 100644 --- a/app/code/community/JR/Api/Model/Catalog/Product/Api/V2.php +++ b/app/code/community/JR/Api/Model/Catalog/Product/Api/V2.php @@ -9,6 +9,39 @@ public function create($type, $set, $sku, $productData, $store = null) $set = Mage::helper('jr_api')->getAttributeSetIdByName($set); } + //If the product exists with diffrent configurable attributes, drop and create a similar product + if($type == 'configurable' && isset($productData->additional_attributes['config_attributes'])) { + + $product = Mage::getModel('catalog/product')->loadByAttribute('sku', $sku); + $configAttributes = explode(',', $productData->additional_attributes['config_attributes']); + + if ($product && !empty($configAttributes)) { + $old_attrs = $product->getTypeInstance(true)->getConfigurableAttributesAsArray($product); + + if((count($old_attrs) != count($configAttributes)) || $old_attrs[0]['attribute_code'] && ($old_attrs[0]['attribute_code'] != $configAttributes[0])) { + + $productData->name = $product->getName(); + $productData->description = $product->getDescription(); + $productData->short_description = $product->getShortDescription(); + $productData->weight = $product->getWeight(); + $productData->price = $product->getPrice(); + $productData->status = $product->getStatus(); + $productData->additional_attributes = array( + 'orig_name' => $product->getData('orig_name'), + 'composition' => $product->getData('composition'), + 'maintenance' => $product->getData('maintenance'), + 'size_chart' => $product->getData('size_chart'), + 'config_attributes' => $productData->additional_attributes['config_attributes'] + ); + $productData->media = array('image' => $product->getData('image')); + $productData->categories = $product->getCategoryIds(); + + Mage::dispatchEvent('catalog_controller_product_delete', array('product' => $product)); + $product->delete(); + } + } + } + return parent::create($type, $set, $sku, $productData, $store); } @@ -26,6 +59,15 @@ protected function _prepareDataForSave($product, $productData) } } + + if (property_exists($productData, 'media')) { + $path = Mage::getBaseDir().'/media/catalog/product'; + if(file_exists($path.$productData->media['image'])) { + $product->addImageToMediaGallery($path.$productData->media['image'], array('image','small_image','thumbnail'), true, false); + } + } + + if (property_exists($productData, 'additional_attributes')) { $singleDataExists = property_exists((object) $productData->additional_attributes, 'single_data'); $multiDataExists = property_exists((object) $productData->additional_attributes, 'multi_data');