Skip to content

Commit 50e7364

Browse files
author
lukaszm-rc
committed
Initial commit
0 parents  commit 50e7364

File tree

15 files changed

+616
-0
lines changed

15 files changed

+616
-0
lines changed

README.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
## Overview
2+
3+
This extension improves default features of Magento API.
4+
5+
It allows you to:
6+
7+
* Associate simple products to configurable or grouped product;
8+
* Specify category names rather than the ids;
9+
* Specify the name of the attribute set rather than the id;
10+
* Specify options labels rather than the ids;
11+
* Specify the website code rather than the id.
12+
13+
## Usage :
14+
15+
Just add to Yours configurable product entity :
16+
$product['associated_skus'] => ['sku_1', 'sku_2'];
17+
18+
If attribute set has more configurable fields than You want, then You should add:
19+
20+
$product['configurable_attributes'] = ['configurable_attribute_id', 'configurable_attribute_code'];
21+
22+
## Installation
23+
24+
### Magento 1.6 - 1.9.x
25+
26+
Install manually:
27+
28+
* Download latest version [here](https://github.com/jreinke/magento-improve-api/archive/master.zip)
29+
* Unzip in Magento root folder
30+
* Clear cache
31+
32+
## How to associate simple products to configurable/grouped product
33+
34+
Please refer to [this article](http://www.bubblecode.net/en/2012/04/20/magento-api-associate-simple-products-to-configurable-or-grouped-product/).
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
3+
/**
4+
* @author Lukasz Mazurek <[email protected]>
5+
*/
6+
class Etk_Api_Block_Adminhtml_System_Config_Fieldset_Hint extends Mage_Adminhtml_Block_Abstract implements Varien_Data_Form_Element_Renderer_Interface {
7+
8+
protected $_template = 'Etk/Api/system/config/fieldset/hint.phtml';
9+
10+
public function render(Varien_Data_Form_Element_Abstract $element) {
11+
return $this->toHtml();
12+
}
13+
14+
}
Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
<?php
2+
3+
class Etk_Api_Helper_Catalog_Product extends Mage_Core_Helper_Abstract {
4+
5+
const CATEGORIES_SEPARATOR_PATH_XML = 'Etk_Api/config/categories_separator';
6+
7+
private $configurableAttributesType; // int/string
8+
9+
/**
10+
* @param Mage_Catalog_Model_Product $product
11+
* @param array $simpleSkus
12+
* @param array $priceChanges
13+
* @return Etk_Api_Helper_Catalog_Product
14+
*/
15+
16+
public function associateProducts(Mage_Catalog_Model_Product $product, $simpleSkus, $priceChanges = array (), $configurableAttributes = array ()) {
17+
if (!empty($simpleSkus)) {
18+
$newProductIds = Mage::getModel('catalog/product')->getCollection()
19+
->addFieldToFilter('sku', array ('in' => (array) $simpleSkus))
20+
->addFieldToFilter('type_id', Mage_Catalog_Model_Product_Type::TYPE_SIMPLE)
21+
->getAllIds();
22+
23+
$oldProductIds = Mage::getModel('catalog/product_type_configurable')->setProduct($product)->getUsedProductCollection()
24+
->addAttributeToSelect('*')
25+
->addFilterByRequiredOptions()
26+
->getAllIds();
27+
28+
$usedProductIds = array_diff($newProductIds, $oldProductIds);
29+
30+
if (!empty($newProductIds) && $product->isConfigurable()) {
31+
$this->_initConfigurableAttributesData($product, $newProductIds, $priceChanges, $configurableAttributes);
32+
}
33+
34+
if (!empty($usedProductIds) && $product->isGrouped()) {
35+
$relations = array_fill_keys($usedProductIds, array ('qty' => 0, 'position' => 0));
36+
$product->setGroupedLinkData($relations);
37+
}
38+
}
39+
40+
return $this;
41+
}
42+
43+
/**
44+
* @param array $categoryNames
45+
* @return array
46+
*/
47+
public function getCategoryIdsByNames($categoryNames) {
48+
$categories = array ();
49+
$separator = $this->_getCatagoriesSeparator();
50+
foreach ($categoryNames as $category) {
51+
if (is_string($category) && !is_numeric($category)) {
52+
$pieces = explode($separator, $category);
53+
$addCategories = array ();
54+
$parentIds = array ();
55+
foreach ($pieces as $level => $name) {
56+
$collection = Mage::getModel('catalog/category')->getCollection()
57+
->setStoreId(0)
58+
->addFieldToFilter('level', $level + 2)
59+
->addAttributeToFilter('name', $name);
60+
if (!empty($parentIds)) {
61+
$collection->getSelect()->where('parent_id IN (?)', $parentIds);
62+
}
63+
$parentIds = array ();
64+
if ($collection->count()) {
65+
foreach ($collection as $category) {
66+
$addCategories[] = (int) $category->getId();
67+
if ($level > 0) {
68+
$addCategories[] = (int) $category->getParentId();
69+
}
70+
$parentIds[] = $category->getId();
71+
}
72+
}
73+
}
74+
if (!empty($addCategories)) {
75+
$categories = array_merge($categories, $addCategories);
76+
}
77+
}
78+
}
79+
80+
return !empty($categories)?$categories:$categoryNames;
81+
}
82+
83+
public function getAttributeKeyByCode($attributeCode) {
84+
$attribute = Mage::getModel('catalog/product')->getResource()->getAttribute($attributeCode);
85+
if ($attribute) {
86+
return $attribute->getId();
87+
}
88+
}
89+
90+
/**
91+
* @param string $attributeCode
92+
* @param string $label
93+
* @return mixed
94+
*/
95+
public function getOptionKeyByLabel($attributeCode, $label) {
96+
$attribute = Mage::getModel('catalog/product')->getResource()
97+
->getAttribute($attributeCode);
98+
if ($attribute && $attribute->getId() && $attribute->usesSource()) {
99+
foreach ($attribute->getSource()->getAllOptions(true, true) as $option) {
100+
if ($label == $option['label']) {
101+
return $option['value'];
102+
}
103+
}
104+
}
105+
106+
return $label;
107+
}
108+
109+
protected function _getCatagoriesSeparator() {
110+
return Mage::getStoreConfig(self::CATEGORIES_SEPARATOR_PATH_XML);
111+
}
112+
113+
/**
114+
* @param Mage_Catalog_Model_Product $mainProduct
115+
* @param array $simpleProductIds
116+
* @param array $priceChanges
117+
* @return Etk_Api_Helper_Catalog_Product
118+
*/
119+
protected function _initConfigurableAttributesData(Mage_Catalog_Model_Product $mainProduct, $simpleProductIds, $priceChanges = array (), $configurableAttributes = array ()) {
120+
if (!$mainProduct->isConfigurable() || empty($simpleProductIds)) {
121+
return $this;
122+
}
123+
124+
$mainProduct->setConfigurableProductsData(array_flip($simpleProductIds));
125+
$productType = $mainProduct->getTypeInstance(true);
126+
$productType->setProduct($mainProduct);
127+
$attributesData = $productType->getConfigurableAttributesAsArray();
128+
129+
if (empty($attributesData)) {
130+
// Auto generation if configurable product has no attribute
131+
$attributeIds = array ();
132+
foreach ($productType->getSetAttributes() as $attribute) {
133+
if ($productType->canUseAttribute($attribute)) {
134+
$attributeIds[] = $attribute->getAttributeId();
135+
}
136+
}
137+
$productType->setUsedProductAttributeIds($attributeIds);
138+
$attributesData = $productType->getConfigurableAttributesAsArray();
139+
}
140+
if (!empty($configurableAttributes)) {
141+
$_before = $configurableAttributes;
142+
$this->_chechAttributesType($configurableAttributes);
143+
$_after = $configurableAttributes;
144+
$log = file_put_contents('magento-api-mod.log', print_r(['before' => $_before, 'after' => $_after, 'attributesData' => $attributesData], true), FILE_APPEND);
145+
146+
foreach ($attributesData as $idx => $val) {
147+
if ($this->configurableAttributesType == 'string') {
148+
if (!in_array($val['label'], $configurableAttributes)) {
149+
unset($attributesData[$idx]);
150+
}
151+
}
152+
else {
153+
if (!in_array($val['attribute_id'], $configurableAttributes)) {
154+
unset($attributesData[$idx]);
155+
}
156+
}
157+
}
158+
}
159+
160+
$products = Mage::getModel('catalog/product')->getCollection()
161+
->addIdFilter($simpleProductIds);
162+
163+
if (count($products)) {
164+
foreach ($attributesData as &$attribute) {
165+
$attribute['label'] = $attribute['frontend_label'];
166+
$attributeCode = $attribute['attribute_code'];
167+
foreach ($products as $product) {
168+
$product->load($product->getId());
169+
$optionId = $product->getData($attributeCode);
170+
$isPercent = 0;
171+
$priceChange = 0;
172+
if (!empty($priceChanges) && isset($priceChanges[$attributeCode])) {
173+
$optionText = $product->getResource()
174+
->getAttribute($attribute['attribute_code'])
175+
->getSource()
176+
->getOptionText($optionId);
177+
if (isset($priceChanges[$attributeCode][$optionText])) {
178+
if (false !== strpos($priceChanges[$attributeCode][$optionText], '%')) {
179+
$isPercent = 1;
180+
}
181+
$priceChange = preg_replace('/[^0-9\.,-]/', '', $priceChanges[$attributeCode][$optionText]);
182+
$priceChange = (float) str_replace(',', '.', $priceChange);
183+
}
184+
}
185+
$attribute['values'][$optionId] = array (
186+
'value_index' => $optionId,
187+
'is_percent' => $isPercent,
188+
'pricing_value' => $priceChange,
189+
);
190+
}
191+
}
192+
$mainProduct->setConfigurableAttributesData($attributesData);
193+
}
194+
195+
return $this;
196+
}
197+
198+
protected function _chechAttributesType(&$configurableAttributes) {
199+
foreach ($configurableAttributes as $key => $_attr) {
200+
if (!is_numeric($_attr)) {
201+
$configurableAttributes[$key] = $this->getAttributeKeyByCode($_attr);
202+
$this->configurableAttributesType = 'string';
203+
}
204+
}
205+
$this->configurableAttributesType = 'int';
206+
return $this->configurableAttributesType;
207+
}
208+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
/**
3+
* @author Lukasz Mazurek <[email protected]>
4+
*/
5+
class Etk_Api_Helper_Data extends Mage_Core_Helper_Abstract
6+
{
7+
/**
8+
* @param string $attrSetName
9+
* @return string
10+
*/
11+
public function getAttributeSetIdByName($attrSetName, $entityType = 'catalog_product')
12+
{
13+
return Mage::getSingleton('catalog/config')
14+
->getAttributeSetId($entityType, $attrSetName);
15+
}
16+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<?php
2+
3+
/**
4+
* @author Lukasz Mazurek <[email protected]>
5+
*/
6+
class Etk_Api_Model_Catalog_Product_Api extends Mage_Catalog_Model_Product_Api
7+
{
8+
public function create($type, $set, $sku, $productData, $store = null)
9+
{
10+
// Allow attribute set name instead of id
11+
if (is_string($set) && !is_numeric($set)) {
12+
$set = Mage::helper('Etk_Api')->getAttributeSetIdByName($set);
13+
}
14+
15+
return parent::create($type, $set, $sku, $productData, $store);
16+
}
17+
18+
protected function _prepareDataForSave($product, $productData)
19+
{
20+
/* @var $product Mage_Catalog_Model_Product */
21+
22+
if (isset($productData['categories'])) {
23+
$categoryIds = Mage::helper('Etk_Api/catalog_product')
24+
->getCategoryIdsByNames((array) $productData['categories']);
25+
if (!empty($categoryIds)) {
26+
$productData['categories'] = array_unique($categoryIds);
27+
}
28+
}
29+
30+
if (isset($productData['website_ids'])) {
31+
$websiteIds = $productData['website_ids'];
32+
foreach ($websiteIds as $i => $websiteId) {
33+
if (!is_numeric($websiteId)) {
34+
$website = Mage::app()->getWebsite($websiteId);
35+
if ($website->getId()) {
36+
$websiteIds[$i] = $website->getId();
37+
}
38+
}
39+
}
40+
$product->setWebsiteIds($websiteIds);
41+
unset($productData['website_ids']);
42+
}
43+
44+
foreach ($productData as $code => $value) {
45+
$productData[$code] = Mage::helper('Etk_Api/catalog_product')
46+
->getOptionKeyByLabel($code, $value);
47+
}
48+
49+
parent::_prepareDataForSave($product, $productData);
50+
51+
if (isset($productData['associated_skus'])) {
52+
$simpleSkus = $productData['associated_skus'];
53+
$priceChanges = isset($productData['price_changes']) ? $productData['price_changes'] : array();
54+
$configurableAttributes = isset($productData['configurable_attributes']) ? $productData['configurable_attributes'] : array();
55+
Mage::helper('Etk_Api/catalog_product')->associateProducts($product, $simpleSkus, $priceChanges, $configurableAttributes);
56+
}
57+
}
58+
}

0 commit comments

Comments
 (0)