Version Notes
This is currently our beta, being tested by some customers. If you wish to join the beta programme, please contact your account manager at eSellelrPro.
Download this release
Release Info
Developer | eSellerPro |
Extension | eSellerProPlugin |
Version | 1.0.0.7 |
Comparing to | |
See all releases |
Code changes from version 1.0.0.6 to 1.0.0.7
- app/code/local/Sandbourne/BulkApi/Helper/Array.php +36 -0
- app/code/local/Sandbourne/BulkApi/Helper/Attribute.php +227 -0
- app/code/local/Sandbourne/BulkApi/Helper/AttributeCache.php +97 -0
- app/code/local/Sandbourne/BulkApi/Helper/AttributeOptionCache.php +40 -0
- app/code/local/Sandbourne/BulkApi/Helper/Category.php +76 -0
- app/code/local/Sandbourne/BulkApi/Helper/CategoryCache.php +55 -0
- app/code/local/Sandbourne/BulkApi/Helper/ConfigurableProduct.php +218 -0
- app/code/local/Sandbourne/BulkApi/Helper/Data.php +17 -0
- app/code/local/Sandbourne/BulkApi/Helper/Image.php +119 -0
- app/code/local/Sandbourne/BulkApi/Helper/RelatedProducts.php +43 -0
- app/code/local/Sandbourne/BulkApi/Helper/TestData.php +561 -0
- app/code/local/Sandbourne/BulkApi/Helper/Utils.php +70 -0
- app/code/local/Sandbourne/BulkApi/Helper/Website.php +120 -0
- app/code/local/Sandbourne/BulkApi/Model/FullImage/Api.php +91 -0
- app/code/local/Sandbourne/BulkApi/Model/FullImage/Api/V2.php +9 -0
- app/code/local/Sandbourne/BulkApi/Model/FullProduct/Api.php +213 -0
- app/code/local/Sandbourne/BulkApi/Model/FullProduct/Api/V2.php +14 -0
- app/code/local/Sandbourne/BulkApi/Model/PartialProduct/Api.php +57 -0
- app/code/local/Sandbourne/BulkApi/Model/PartialProduct/Api/V2.php +11 -0
- app/code/local/Sandbourne/BulkApi/Model/testatts.php +16 -0
- app/code/local/Sandbourne/BulkApi/etc/api.xml +79 -0
- app/code/local/Sandbourne/BulkApi/etc/config.xml +20 -0
- app/code/local/Sandbourne/BulkApi/etc/wsdl.xml +98 -0
- app/etc/modules/Sandbourne_BulkApi.xml +9 -0
- package.xml +23 -8
app/code/local/Sandbourne/BulkApi/Helper/Array.php
ADDED
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Sandbourne_BulkApi_Helper_Array extends Mage_Core_Helper_Abstract
|
4 |
+
{
|
5 |
+
public function __construct()
|
6 |
+
{
|
7 |
+
//$this->_debug('Array Helper constructed');
|
8 |
+
}
|
9 |
+
|
10 |
+
public function findItemUsingEquals($searchKey, $searchValue, $array)
|
11 |
+
{
|
12 |
+
$key = $this->findItemKeyUsingEquals($searchKey, $searchValue, $array);
|
13 |
+
if (!is_null($key))
|
14 |
+
{
|
15 |
+
return $array[$key];
|
16 |
+
}
|
17 |
+
return NULL;
|
18 |
+
}
|
19 |
+
|
20 |
+
public function findItemKeyUsingEquals($searchKey, $searchValue, $array)
|
21 |
+
{
|
22 |
+
foreach($array as $key=>$value)
|
23 |
+
{
|
24 |
+
if ($value[$searchKey] === $searchValue)
|
25 |
+
{
|
26 |
+
return $key;
|
27 |
+
}
|
28 |
+
}
|
29 |
+
return NULL;
|
30 |
+
}
|
31 |
+
|
32 |
+
public function _debug($message)
|
33 |
+
{
|
34 |
+
Mage::log($message);
|
35 |
+
}
|
36 |
+
}
|
app/code/local/Sandbourne/BulkApi/Helper/Attribute.php
ADDED
@@ -0,0 +1,227 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Attribute Helper Class.
|
5 |
+
*/
|
6 |
+
|
7 |
+
class Sandbourne_BulkApi_Helper_Attribute extends Mage_Core_Helper_Abstract
|
8 |
+
{
|
9 |
+
|
10 |
+
public function __construct()
|
11 |
+
{
|
12 |
+
//$this->_debug('Attribute Helper constructed');
|
13 |
+
}
|
14 |
+
|
15 |
+
public function getDefaultAttributeSetId()
|
16 |
+
{
|
17 |
+
$entityTypeId = Mage::getModel('eav/entity')->setType('catalog_product')->getTypeId();
|
18 |
+
$attributeSetCollection = Mage::getResourceModel('eav/entity_attribute_set_collection')->setEntityTypeFilter($entityTypeId)->addFilter('attribute_set_name', 'Default');
|
19 |
+
|
20 |
+
foreach($attributeSetCollection as $attributeSet)
|
21 |
+
{
|
22 |
+
return $attributeSet->getId();
|
23 |
+
}
|
24 |
+
}
|
25 |
+
|
26 |
+
public function setVariationSpecificValues($magentoProduct, $variationData, $attributeCache)
|
27 |
+
{
|
28 |
+
//$this->_debug("**** setVariationSpecificValues ****");
|
29 |
+
|
30 |
+
// We need to interogate the name of the attribute to make sure it is valid
|
31 |
+
$productUtils = Mage::helper('bulkapi/utils');
|
32 |
+
|
33 |
+
if (isset($variationData->VariationSpecifics))
|
34 |
+
{
|
35 |
+
foreach ($variationData->VariationSpecifics->NameValueList as $nameValueList)
|
36 |
+
{
|
37 |
+
// Check the custom field name about to be added is valid
|
38 |
+
if ($productUtils->isCustomFieldValid($nameValueList->Name) === true)
|
39 |
+
{
|
40 |
+
$replacedChars = $productUtils->replaceInvalidChars($nameValueList->Name);
|
41 |
+
$this->setCustomFieldValue($magentoProduct, $replacedChars, $nameValueList->Value, $attributeCache);
|
42 |
+
}
|
43 |
+
}
|
44 |
+
}
|
45 |
+
}
|
46 |
+
|
47 |
+
public function setCustomFieldGroupValues($magentoProduct, $productData, $attributeCache)
|
48 |
+
{
|
49 |
+
if (isset($productData->CustomGroups))
|
50 |
+
{
|
51 |
+
foreach ($productData->CustomGroups->CustomGroup as $customGroup)
|
52 |
+
{
|
53 |
+
// Test we want to import from this Customfield Group
|
54 |
+
// What Customfield Groups do we want to use, or all of them if field is blank?
|
55 |
+
// (JC) - Change this approach, if blank use the default "Magento" group.
|
56 |
+
if ($this->canProcessCustomFieldGroup($productData->UseCustomGroups, $customGroup['groupName']))
|
57 |
+
{
|
58 |
+
$this->setCustomFieldValues($magentoProduct, $customGroup, $attributeCache);
|
59 |
+
}
|
60 |
+
}
|
61 |
+
}
|
62 |
+
}
|
63 |
+
|
64 |
+
public function setCustomFieldValues($magentoProduct, $customGroup, $attributeCache)
|
65 |
+
{
|
66 |
+
// We need to interogate the name of the attribute to make sure it is valid
|
67 |
+
$productUtils = Mage::helper('bulkapi/utils');
|
68 |
+
|
69 |
+
foreach ($customGroup->CustomFields->NameValueList as $nameValueList)
|
70 |
+
{
|
71 |
+
// Check this attribute name is not reserved before adding it
|
72 |
+
if ($productUtils->isAttributeReserved($nameValueList->Name) === false)
|
73 |
+
{
|
74 |
+
// Check the custom field name about to be added is valid
|
75 |
+
if ($productUtils->isCustomFieldValid($nameValueList->Name) === true)
|
76 |
+
{
|
77 |
+
$replacedChars = $productUtils->replaceInvalidChars($nameValueList->Name);
|
78 |
+
$this->setCustomFieldValue($magentoProduct, $replacedChars, $nameValueList->Value, $attributeCache);
|
79 |
+
}
|
80 |
+
}
|
81 |
+
}
|
82 |
+
}
|
83 |
+
|
84 |
+
private function canProcessCustomFieldGroup($customFieldGroupToUse, $customFieldGroupName)
|
85 |
+
{
|
86 |
+
$retVal = false;
|
87 |
+
$FieldsToUse = trim((string)$customFieldGroupToUse);
|
88 |
+
$FieldGroupName = trim((string)$customFieldGroupName);
|
89 |
+
|
90 |
+
// (JC) - If blank use the default "Magento" group if it exists.
|
91 |
+
if (empty($FieldsToUse))
|
92 |
+
{
|
93 |
+
$FieldsToUse = "Magento";
|
94 |
+
}
|
95 |
+
|
96 |
+
//if ((strpos((string)$customFieldGroupToUse, (string)$customFieldGroupName) !== false) || strlen(trim($customFieldGroupToUse)) === 0)
|
97 |
+
if (strpos($FieldsToUse, $FieldGroupName) !== false)
|
98 |
+
{
|
99 |
+
$retVal = true;
|
100 |
+
}
|
101 |
+
return $retVal;
|
102 |
+
}
|
103 |
+
|
104 |
+
private function setCustomFieldValue($magentoProduct, $attributeName, $attributeValue, $attributeCache)
|
105 |
+
{
|
106 |
+
$attribute = $attributeCache->getAttribute($attributeName);
|
107 |
+
if (is_null($attribute))
|
108 |
+
{
|
109 |
+
$attribute = $this->createAttribute($attributeName, $magentoProduct->getAttributeSetId());
|
110 |
+
$attributeCache->addAttribute($attribute);
|
111 |
+
}
|
112 |
+
//We are not going to mess about with putting attributes
|
113 |
+
//in sets if the customer has organised it differently
|
114 |
+
if ($attribute->isInSet($magentoProduct->getAttributeSetId()))
|
115 |
+
{
|
116 |
+
$this->getDefaultAttributeGroupId($magentoProduct->getAttributeSetId());
|
117 |
+
if (!is_null($attribute))
|
118 |
+
{
|
119 |
+
if ($attribute->usesSource())
|
120 |
+
{
|
121 |
+
$attributeOption = $attributeCache->getAttributeOption($attributeName, $attributeValue);
|
122 |
+
//$attributeValueId = $this->findAttributeValueId($attributeValue, $attribute->getSource()->getAllOptions());
|
123 |
+
//$this->_debug('attribute value id:'.$attributeValueId);
|
124 |
+
if (is_null($attributeOption))
|
125 |
+
{
|
126 |
+
$attributeOption = $this->addAttributeOption($attributeValue, $attribute, $attributeCache);
|
127 |
+
}
|
128 |
+
//$this->_debug('setting attribute: '.$attribute->getAttributeCode().' to: '.$attributeOption['value']);
|
129 |
+
//$this->_debug('previous attribute value: '.$attribute->getAttributeCode().' to: '.$magentoProduct->getData($attribute->getAttributeCode()));
|
130 |
+
|
131 |
+
$magentoProduct->setData($attribute->getAttributeCode(), $attributeOption['value']);
|
132 |
+
}
|
133 |
+
else
|
134 |
+
{
|
135 |
+
|
136 |
+
}
|
137 |
+
//$this->_debug($attribute->getFrontendLabel().':'.$attribute->getBackendType());
|
138 |
+
}
|
139 |
+
}
|
140 |
+
}
|
141 |
+
|
142 |
+
private function createAttribute($attributeName, $attributeSetId)
|
143 |
+
{
|
144 |
+
//$this->_debug('call to create attribute: '.$attributeName.$attributeSetId);
|
145 |
+
$attribute = Mage::getModel('catalog/resource_eav_attribute');
|
146 |
+
$data = array();
|
147 |
+
|
148 |
+
$attributeCode = strtolower($attributeName);
|
149 |
+
//$attributeCode = str_replace(' ', '_', $attributeCode);
|
150 |
+
//$this->_debug($attributeCode);
|
151 |
+
//$this->_debug($attributeName);
|
152 |
+
|
153 |
+
$data['attribute_code'] = $attributeCode;
|
154 |
+
$data['frontend_label'] = array($attributeName, '','','','');
|
155 |
+
$data['apply_to'] = array('simple', 'configurable');
|
156 |
+
$data['is_configurable'] = '1';
|
157 |
+
$data['is_filterable'] = '1';
|
158 |
+
$data['is_filterable_in_search'] = '1';
|
159 |
+
$data['frontend_input'] = 'select';
|
160 |
+
$data['backend_type'] = 'int';
|
161 |
+
$data['is_global'] = Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_GLOBAL;
|
162 |
+
$attribute->addData($data);
|
163 |
+
|
164 |
+
$attribute->setAttributeSetId($attributeSetId);
|
165 |
+
$defaultGroupId = $this->getDefaultAttributeGroupId($attributeSetId);
|
166 |
+
$attribute->setAttributeGroupId($defaultGroupId);
|
167 |
+
|
168 |
+
//$this->_debug('going to create attribute with set id: '.$attribute->getAttributeSetId().' and group id: '.$attribute->getAttributeGroupId());
|
169 |
+
$entityTypeID = Mage::getModel('eav/entity')->setType('catalog_product')->getTypeId();
|
170 |
+
$attribute->setEntityTypeId($entityTypeID);
|
171 |
+
$attribute->setIsUserDefined(1);
|
172 |
+
$attribute->save();
|
173 |
+
//$this->_debug('created attribute with id'.$attribute->getId());
|
174 |
+
return $attribute;
|
175 |
+
}
|
176 |
+
|
177 |
+
//to fetch the attribute group collection
|
178 |
+
private function getDefaultAttributeGroupId($attributeSetId)
|
179 |
+
{
|
180 |
+
$attributeGroups = Mage::getResourceModel('eav/entity_attribute_group_collection');
|
181 |
+
$attributeGroups->setAttributeSetFilter($attributeSetId);
|
182 |
+
$attributeGroups->load();
|
183 |
+
$firstGroupId = -1;
|
184 |
+
|
185 |
+
foreach($attributeGroups as $group)
|
186 |
+
{
|
187 |
+
if ($firstGroupId === -1)
|
188 |
+
{
|
189 |
+
$firstGroupId = $group->getId();
|
190 |
+
}
|
191 |
+
|
192 |
+
if ($group->getDefaultId() == 1)
|
193 |
+
{
|
194 |
+
return $group->getId();
|
195 |
+
}
|
196 |
+
}
|
197 |
+
return $firstGroupId;
|
198 |
+
}
|
199 |
+
/*
|
200 |
+
$attributeSetCollection = Mage::getResourceModel('eav/entity_attribute_group_collection')
|
201 |
+
->load();*/
|
202 |
+
|
203 |
+
private function addAttributeOption($optionValue, $attribute, $attributeCache)
|
204 |
+
{
|
205 |
+
$optionLabels[0] = $optionValue;
|
206 |
+
$optionData = array();
|
207 |
+
$optionData['value'] = array('option_1' => $optionLabels);
|
208 |
+
$optionData['order'] = array('option_1' => 1);//order
|
209 |
+
|
210 |
+
$modelData = array('option' => $optionData);
|
211 |
+
|
212 |
+
$attribute->addData($modelData);
|
213 |
+
$attribute->save();
|
214 |
+
|
215 |
+
//we need to load the attribute again to get the newly added option
|
216 |
+
$resetAttribute = Mage::getModel('catalog/resource_eav_attribute')->load($attribute->getId());
|
217 |
+
$attributeCache->resetAttribute($resetAttribute);
|
218 |
+
$attributeOption = $attributeCache->getAttributeOption($resetAttribute->getAttributeCode(), $optionValue);
|
219 |
+
|
220 |
+
return $attributeOption;
|
221 |
+
}
|
222 |
+
|
223 |
+
public function _debug($message)
|
224 |
+
{
|
225 |
+
Mage::log($message);
|
226 |
+
}
|
227 |
+
}
|
app/code/local/Sandbourne/BulkApi/Helper/AttributeCache.php
ADDED
@@ -0,0 +1,97 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Sandbourne_BulkApi_Helper_AttributeCache extends Mage_Core_Helper_Abstract
|
4 |
+
{
|
5 |
+
private $attributeArray = array();
|
6 |
+
private $attributeOptionCacheArray = array();
|
7 |
+
|
8 |
+
public function __construct()
|
9 |
+
{
|
10 |
+
//$this->_debug('AttributeCache Helper constructed');
|
11 |
+
}
|
12 |
+
|
13 |
+
public function resetCache($attributes)
|
14 |
+
{
|
15 |
+
$this->attributeArray = array();
|
16 |
+
$this->attributeOptionCacheArray = array();
|
17 |
+
foreach ($attributes as $attribute)
|
18 |
+
{
|
19 |
+
$this->addAttribute($attribute);
|
20 |
+
/*if ($attribute->usesSource())
|
21 |
+
{
|
22 |
+
$this->_debug('attribute name:'.$attribute->getName());
|
23 |
+
$this->_debug('attribute source class:'.get_class($attribute->getSource()));
|
24 |
+
}*/
|
25 |
+
}
|
26 |
+
}
|
27 |
+
|
28 |
+
public function addAttribute($attribute)
|
29 |
+
{
|
30 |
+
$lowerCaseAttributeCode = strtolower($attribute->getAttributeCode());
|
31 |
+
//$this->_debug('adding attribute to cache:'.$lowerCaseAttributeCode);
|
32 |
+
//$this->_debug('adding attribute to cache with set id: '.$attribute->getAttributeSetId().' and group id: '.$attribute->getAttributeGroupId());
|
33 |
+
$this->attributeArray[$lowerCaseAttributeCode] = $attribute;
|
34 |
+
}
|
35 |
+
|
36 |
+
public function resetAttribute($attribute)
|
37 |
+
{
|
38 |
+
$lowerCaseAttributeCode = strtolower($attribute->getAttributeCode());
|
39 |
+
$this->attributeArray[$lowerCaseAttributeCode] = $attribute;
|
40 |
+
if (array_key_exists($lowerCaseAttributeCode, $this->attributeOptionCacheArray))
|
41 |
+
{
|
42 |
+
$attributeOptionCache = Mage::helper('bulkapi/attributeOptionCache');
|
43 |
+
$options = $attribute->getSource()->getAllOptions();
|
44 |
+
$attributeOptionCache->resetCache($options);
|
45 |
+
$this->attributeOptionCacheArray[$lowerCaseAttributeCode] = $attributeOptionCache;
|
46 |
+
}
|
47 |
+
}
|
48 |
+
|
49 |
+
public function getAttribute($attributeCode)
|
50 |
+
{
|
51 |
+
$lowerCaseAttributeCode = strtolower($attributeCode);
|
52 |
+
if (array_key_exists($lowerCaseAttributeCode, $this->attributeArray))
|
53 |
+
{
|
54 |
+
//$this->_debug('attribute found in cache:'.$lowerCaseAttributeCode);
|
55 |
+
return $this->attributeArray[$lowerCaseAttributeCode];
|
56 |
+
}
|
57 |
+
//$this->_debug('attribute not found in cache:'.$lowerCaseAttributeCode);
|
58 |
+
}
|
59 |
+
|
60 |
+
public function getAttributeOption($attributeCode, $attributeOptionLabel)
|
61 |
+
{
|
62 |
+
$attribute = $this->getAttribute($attributeCode);
|
63 |
+
if (!is_null($attribute))
|
64 |
+
{
|
65 |
+
$lowerCaseAttributeCode = strtolower($attributeCode);
|
66 |
+
if (!array_key_exists($lowerCaseAttributeCode, $this->attributeOptionCacheArray))
|
67 |
+
{
|
68 |
+
$attributeOptionCache = Mage::helper('bulkapi/attributeOptionCache');
|
69 |
+
$options = $attribute->getSource()->getAllOptions();
|
70 |
+
$attributeOptionCache->resetCache($options);
|
71 |
+
$this->attributeOptionCacheArray[$lowerCaseAttributeCode] = $attributeOptionCache;
|
72 |
+
}
|
73 |
+
|
74 |
+
$attributeOptionCache = $this->attributeOptionCacheArray[$lowerCaseAttributeCode];
|
75 |
+
return $attributeOptionCache->getAttributeOption($attributeOptionLabel);
|
76 |
+
}
|
77 |
+
}
|
78 |
+
|
79 |
+
public function addAttributeOption($attributeCode, $attributeOption)
|
80 |
+
{
|
81 |
+
$attribute = $this->getAttribute($attributeCode);
|
82 |
+
if (!is_null($attribute))
|
83 |
+
{
|
84 |
+
$lowerCaseAttributeCode = strtolower($attributeCode);
|
85 |
+
if (array_key_exists($lowerCaseAttributeCode, $this->attributeOptionCacheArray))
|
86 |
+
{
|
87 |
+
$attributeOptionCache = $this->attributeOptionCacheArray[$lowerCaseAttributeCode];
|
88 |
+
$attributeOptionCache->addAttributeOption($attributeOption);
|
89 |
+
}
|
90 |
+
}
|
91 |
+
}
|
92 |
+
|
93 |
+
private function _debug($message)
|
94 |
+
{
|
95 |
+
Mage::log($message);
|
96 |
+
}
|
97 |
+
}
|
app/code/local/Sandbourne/BulkApi/Helper/AttributeOptionCache.php
ADDED
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Sandbourne_BulkApi_Helper_AttributeOptionCache extends Mage_Core_Helper_Abstract
|
4 |
+
{
|
5 |
+
private $attributeOptionArray = array();
|
6 |
+
|
7 |
+
public function __construct()
|
8 |
+
{
|
9 |
+
//$this->_debug('AttributeOptionCache Helper constructed');
|
10 |
+
}
|
11 |
+
|
12 |
+
public function resetCache($attributeOptions)
|
13 |
+
{
|
14 |
+
$this->atrributeOptionArray = array();
|
15 |
+
foreach ($attributeOptions as $attributeOption)
|
16 |
+
{
|
17 |
+
$this->addAttributeOption($attributeOption);
|
18 |
+
}
|
19 |
+
}
|
20 |
+
|
21 |
+
public function getAttributeOption($attributeOptionLabel)
|
22 |
+
{
|
23 |
+
$lowerCaseLabel = strtolower($attributeOptionLabel);
|
24 |
+
if (array_key_exists($lowerCaseLabel, $this->attributeOptionArray))
|
25 |
+
{
|
26 |
+
return $this->attributeOptionArray[$lowerCaseLabel];
|
27 |
+
}
|
28 |
+
}
|
29 |
+
|
30 |
+
public function addAttributeOption($attributeOption)
|
31 |
+
{
|
32 |
+
$lowerCaseLabel = strtolower($attributeOption['label']);
|
33 |
+
$this->attributeOptionArray[$lowerCaseLabel] = $attributeOption;
|
34 |
+
}
|
35 |
+
|
36 |
+
private function _debug($message)
|
37 |
+
{
|
38 |
+
Mage::log($message);
|
39 |
+
}
|
40 |
+
}
|
app/code/local/Sandbourne/BulkApi/Helper/Category.php
ADDED
@@ -0,0 +1,76 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Sandbourne_BulkApi_Helper_Category extends Mage_Core_Helper_Abstract
|
4 |
+
{
|
5 |
+
public function __construct()
|
6 |
+
{
|
7 |
+
//$this->_debug('Category Helper constructed');
|
8 |
+
}
|
9 |
+
|
10 |
+
public function setProductCategories($magentoProduct, $productData)
|
11 |
+
{
|
12 |
+
$categoryTreeModel = Mage::getModel('catalog/category')->getTreeModel();
|
13 |
+
$categoryTreeModel->load();
|
14 |
+
$categoryCache = Mage::helper('bulkapi/categoryCache');
|
15 |
+
$categoryCache->resetCache($categoryTreeModel->getCollection());
|
16 |
+
|
17 |
+
//$rootCategories = $categoryCache->getTopLevelCategories();
|
18 |
+
|
19 |
+
$categoryIds = array();
|
20 |
+
foreach ($productData->ProductCategories->ProductCategory as $productCategory)
|
21 |
+
{
|
22 |
+
//$magentoCategories = $rootCategories;
|
23 |
+
|
24 |
+
//$this->_debug((string)$productCategory);
|
25 |
+
$categoryParts = explode('>', (string)$productCategory);
|
26 |
+
$foundCategory = NULL;
|
27 |
+
$path = '1';
|
28 |
+
$currentParentID = 1;
|
29 |
+
|
30 |
+
foreach($categoryParts as $categoryPart)
|
31 |
+
{
|
32 |
+
$foundCategory = $categoryCache->findCategory($currentParentID, $categoryPart);
|
33 |
+
//$foundCategory = $this->findCategory($magentoCategories, $categoryPart);
|
34 |
+
if (isset($foundCategory))
|
35 |
+
{
|
36 |
+
//$magentoCategories = $foundCategory->getChildrenCategories();
|
37 |
+
}
|
38 |
+
else
|
39 |
+
{
|
40 |
+
$foundCategory = Mage::getModel('catalog/category');
|
41 |
+
$foundCategory->setStoreId(0);
|
42 |
+
$foundCategory->setName($categoryPart);
|
43 |
+
$foundCategory->setPath($path);
|
44 |
+
$foundCategory->setIsActive(1);
|
45 |
+
$foundCategory->save();
|
46 |
+
$categoryCache->addCategory($foundCategory);
|
47 |
+
//$magentoCategories = $foundCategory->getChildrenCategories();
|
48 |
+
}
|
49 |
+
$path = $path.'/'.$foundCategory->getId();
|
50 |
+
$currentParentID = $foundCategory->getId();
|
51 |
+
}
|
52 |
+
if (isset($foundCategory))
|
53 |
+
{
|
54 |
+
//$this->_debug('found:'.$foundCategory->getName());
|
55 |
+
array_push($categoryIds, $foundCategory->getId());
|
56 |
+
}
|
57 |
+
}
|
58 |
+
$magentoProduct->setCategoryIds($categoryIds);
|
59 |
+
}
|
60 |
+
|
61 |
+
private function findCategory($magentoCategories, $categoryName)
|
62 |
+
{
|
63 |
+
foreach($magentoCategories as $magentoCategory)
|
64 |
+
{
|
65 |
+
if (strcmp($magentoCategory->getName(), $categoryName)==0)
|
66 |
+
{
|
67 |
+
return $magentoCategory;
|
68 |
+
}
|
69 |
+
}
|
70 |
+
}
|
71 |
+
|
72 |
+
private function _debug($message)
|
73 |
+
{
|
74 |
+
Mage::log($message);
|
75 |
+
}
|
76 |
+
}
|
app/code/local/Sandbourne/BulkApi/Helper/CategoryCache.php
ADDED
@@ -0,0 +1,55 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Sandbourne_BulkApi_Helper_CategoryCache extends Mage_Core_Helper_Abstract
|
4 |
+
{
|
5 |
+
private $categoryArray = array();
|
6 |
+
|
7 |
+
public function __construct()
|
8 |
+
{
|
9 |
+
//$this->_debug('CategoryCache Helper constructed');
|
10 |
+
}
|
11 |
+
|
12 |
+
public function resetCache($categories)
|
13 |
+
{
|
14 |
+
$this->categoryArray = array();
|
15 |
+
foreach($categories as $category)
|
16 |
+
{
|
17 |
+
$this->addCategory($category);
|
18 |
+
}
|
19 |
+
}
|
20 |
+
|
21 |
+
public function addCategory($category)
|
22 |
+
{
|
23 |
+
array_push($this->categoryArray, $category);
|
24 |
+
}
|
25 |
+
|
26 |
+
public function getTopLevelCategories()
|
27 |
+
{
|
28 |
+
$rootCategories = array();
|
29 |
+
foreach($this->categoryArray as $magentoCategory)
|
30 |
+
{
|
31 |
+
if ($magentoCategory->getLevel() == 1)
|
32 |
+
{
|
33 |
+
array_push($rootCategories, $magentoCategory);
|
34 |
+
}
|
35 |
+
}
|
36 |
+
return $rootCategories;
|
37 |
+
}
|
38 |
+
|
39 |
+
public function findCategory($parentID, $categoryName)
|
40 |
+
{
|
41 |
+
foreach($this->categoryArray as $magentoCategory)
|
42 |
+
{
|
43 |
+
if ($magentoCategory->parent_id == $parentID &&
|
44 |
+
strcmp($magentoCategory->name, $categoryName) == 0)
|
45 |
+
{
|
46 |
+
return $magentoCategory;
|
47 |
+
}
|
48 |
+
}
|
49 |
+
}
|
50 |
+
|
51 |
+
private function _debug($message)
|
52 |
+
{
|
53 |
+
Mage::log($message);
|
54 |
+
}
|
55 |
+
}
|
app/code/local/Sandbourne/BulkApi/Helper/ConfigurableProduct.php
ADDED
@@ -0,0 +1,218 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Sandbourne_BulkApi_Helper_ConfigurableProduct extends Mage_Core_Helper_Abstract
|
4 |
+
{
|
5 |
+
public function __construct()
|
6 |
+
{
|
7 |
+
//$this->_debug('ConfigurableProduct Helper constructed');
|
8 |
+
}
|
9 |
+
|
10 |
+
public function setConfigurableProducts($magentoProduct, $productData, $attributeCache)
|
11 |
+
{
|
12 |
+
$attributeHelper = Mage::helper('bulkapi/attribute');
|
13 |
+
$arrayHelper = Mage::helper('bulkapi/array');
|
14 |
+
|
15 |
+
$this->setupSimpleProducts($magentoProduct, $productData, $attributeCache);
|
16 |
+
|
17 |
+
$usedAttributes = $this->getUsedProductAttributes($productData, $attributeCache);
|
18 |
+
|
19 |
+
$configurableAttributesData = $this->buildConfigurableAttributesData($usedAttributes, $magentoProduct, $productData, $attributeCache);
|
20 |
+
|
21 |
+
$usedAttributeIDs = array();
|
22 |
+
foreach($configurableAttributesData as $configurableAttribute)
|
23 |
+
{
|
24 |
+
array_push($usedAttributeIDs, $configurableAttribute['attribute_id']);
|
25 |
+
}
|
26 |
+
|
27 |
+
$configurableProductId = $magentoProduct->getId();
|
28 |
+
if (!isset($configurableProductId))
|
29 |
+
{
|
30 |
+
//$this->_debug('setting used product attribute ids');
|
31 |
+
$magentoProduct->setUsedProductAttributeIds($usedAttributeIDs);
|
32 |
+
}
|
33 |
+
|
34 |
+
//$this->_debug('configurable product attribute IDs');
|
35 |
+
//$this->_debug($usedAttributeIDs);
|
36 |
+
|
37 |
+
$configurableProductData = $this->buildConfigurableProductsData($magentoProduct, $productData, $attributeCache);
|
38 |
+
//$this->_debug($configurableProductData);
|
39 |
+
//$magentoProduct->setCanSaveConfigurableAttributes(true);
|
40 |
+
//$magentoProduct->setCanSaveCustomOptions(true);
|
41 |
+
$magentoProduct->setConfigurableProductsData($configurableProductData);
|
42 |
+
if (!isset($configurableProductId))
|
43 |
+
{
|
44 |
+
$magentoProduct->setConfigurableAttributesData($configurableAttributesData);
|
45 |
+
}
|
46 |
+
}
|
47 |
+
|
48 |
+
private function setupSimpleProducts($magentoProduct, $productData, $attributeCache)
|
49 |
+
{
|
50 |
+
$attributeHelper = Mage::helper('bulkapi/attribute');
|
51 |
+
foreach ($productData->Variations->Variation as $variationData)
|
52 |
+
{
|
53 |
+
$variationProductID = Mage::getModel('catalog/product')->getIdBySku($variationData->StockNumber);
|
54 |
+
if ($variationProductID > 0)
|
55 |
+
{
|
56 |
+
$simpleProduct = Mage::getModel('catalog/product')->load($variationProductID);
|
57 |
+
}
|
58 |
+
else
|
59 |
+
{
|
60 |
+
$simpleProduct = $this->createSimpleProduct($magentoProduct, $variationData);
|
61 |
+
}
|
62 |
+
|
63 |
+
$attributeHelper->setVariationSpecificValues($simpleProduct, $variationData, $attributeCache);
|
64 |
+
$simpleProduct->save();
|
65 |
+
}
|
66 |
+
}
|
67 |
+
|
68 |
+
private function buildConfigurableProductsData($magentoProduct, $productData, $attributeCache)
|
69 |
+
{
|
70 |
+
foreach ($productData->Variations->Variation as $variationData)
|
71 |
+
{
|
72 |
+
//$this->_debug($variationData->StockNumber);
|
73 |
+
$variationProductID = Mage::getModel('catalog/product')->getIdBySku($variationData->StockNumber);
|
74 |
+
//$this->_debug('simple product id:'.$variationProductID);
|
75 |
+
|
76 |
+
$associatedProductData = array();
|
77 |
+
//$associatedProductData['attribute_id'] = 92;
|
78 |
+
$configurableProductData[$variationProductID] = $associatedProductData;
|
79 |
+
}
|
80 |
+
return $configurableProductData;
|
81 |
+
}
|
82 |
+
|
83 |
+
private function buildConfigurableAttributesData($usedAttributes, $magentoProduct, $productData, $attributeCache)
|
84 |
+
{
|
85 |
+
$attributeHelper = Mage::helper('bulkapi/attribute');
|
86 |
+
$arrayHelper = Mage::helper('bulkapi/array');
|
87 |
+
|
88 |
+
//$attributesArray = $magentoProduct->getTypeInstance(true)->getConfigurableAttributesAsArray($magentoProduct);
|
89 |
+
//$this->_debug($attributes_array);
|
90 |
+
$attributesArray = array();
|
91 |
+
|
92 |
+
foreach ($usedAttributes as $usedAttribute)
|
93 |
+
{
|
94 |
+
$configurableAttributeIndex = $arrayHelper->findItemKeyUsingEquals('attribute_id', $usedAttribute->getId(), $attributesArray);
|
95 |
+
|
96 |
+
$configurableAttribute = array();
|
97 |
+
if (!is_null($configurableAttributeIndex))
|
98 |
+
{
|
99 |
+
$configurableAttribute = $attributesArray[$configurableAttributeIndex];
|
100 |
+
}
|
101 |
+
else
|
102 |
+
{
|
103 |
+
$configurableAttribute['attribute_id'] = $usedAttribute->getId();
|
104 |
+
$configurableAttribute['values'] = array();
|
105 |
+
$configurableAttributeIndex = array_push($attributesArray, $configurableAttribute) - 1;
|
106 |
+
}
|
107 |
+
|
108 |
+
$values = $configurableAttribute['values'];
|
109 |
+
|
110 |
+
foreach ($productData->Variations->Variation as $variationData)
|
111 |
+
{
|
112 |
+
$productAttributeValue = $this->findProductAttributeValue($usedAttribute->getAttributeCode(), $variationData);
|
113 |
+
if (!is_null($productAttributeValue))
|
114 |
+
{
|
115 |
+
//got the correct attribute. Now get it's value
|
116 |
+
$attributeOption = $attributeCache->getAttributeOption($usedAttribute->getAttributeCode(), $productAttributeValue);
|
117 |
+
|
118 |
+
//if null need to add another attribute option and set it on the simple product
|
119 |
+
if (!is_null($attributeOption))
|
120 |
+
{
|
121 |
+
//$this->_debug($attributeOption);
|
122 |
+
//find the value section in $configurableAttributeArray
|
123 |
+
//$configurableAttributeValueArray = $this->findConfigurableAttributeValueArray($attributeOption['value'], $configurableAttributeArray['values']);
|
124 |
+
$valueItem = $arrayHelper->findItemUsingEquals('value_index', $attributeOption['value'], $values);
|
125 |
+
if (is_null($valueItem))
|
126 |
+
{
|
127 |
+
$valueItem = array();
|
128 |
+
$valueItem['value_index'] = $attributeOption['value'];
|
129 |
+
$valueItem['pricing_value'] = 0;
|
130 |
+
$valueItem['is_percent'] = 0;
|
131 |
+
array_push($attributesArray[$configurableAttributeIndex]['values'], $valueItem);
|
132 |
+
}
|
133 |
+
}
|
134 |
+
}
|
135 |
+
}
|
136 |
+
}
|
137 |
+
return $attributesArray;
|
138 |
+
}
|
139 |
+
|
140 |
+
private function createSimpleProduct($configurableProduct, $variationData)
|
141 |
+
{
|
142 |
+
$simpleProduct = Mage::getModel('catalog/product');
|
143 |
+
$simpleProduct->setWebsiteIds(array(1));
|
144 |
+
$simpleProduct->setSku($variationData->StockNumber);
|
145 |
+
$simpleProduct->setName($variationData->StockNumber);//need to change to parent name plus variation values
|
146 |
+
$simpleProduct->setTypeId(Mage_Catalog_Model_Product_Type::TYPE_SIMPLE);
|
147 |
+
$simpleProduct->setAttributeSetId($configurableProduct->getAttributeSetId());
|
148 |
+
$simpleProduct->setVisibility(Mage_Catalog_Model_Product_Visibility::VISIBILITY_NOT_VISIBLE);
|
149 |
+
$simpleProduct->setPrice($variationData->SellPrice);
|
150 |
+
$simpleProduct->setTaxClassId(2);
|
151 |
+
$simpleProduct->setWeight(1);
|
152 |
+
$simpleProduct->setDescription('description');
|
153 |
+
$simpleProduct->setShortDescription('short description');
|
154 |
+
$simpleProduct->setStatus(Mage_Catalog_Model_Product_Status::STATUS_ENABLED);
|
155 |
+
|
156 |
+
$stockData = array();
|
157 |
+
$stockData['qty'] = $variationData->StockLevel;
|
158 |
+
$inStock = ($variationData->StockLevel > 0 ? 1 : 0);
|
159 |
+
$stockData['is_in_stock'] = $inStock;
|
160 |
+
|
161 |
+
$simpleProduct->setStockData($stockData);
|
162 |
+
|
163 |
+
return $simpleProduct;
|
164 |
+
}
|
165 |
+
|
166 |
+
private function getUsedProductAttributes($productData, $attributeCache)
|
167 |
+
{
|
168 |
+
$utilsHelper = Mage::helper('bulkapi/utils');
|
169 |
+
|
170 |
+
//$this->_debug('getUsedProductAttributes called');
|
171 |
+
$attributeNames = array();
|
172 |
+
if (isset($productData->Variations))
|
173 |
+
{
|
174 |
+
foreach ($productData->Variations->Variation as $variationData)
|
175 |
+
{
|
176 |
+
foreach ($variationData->VariationSpecifics->NameValueList as $nameValueItem)
|
177 |
+
{
|
178 |
+
if (!in_array($nameValueItem->Name, $attributeNames))
|
179 |
+
{
|
180 |
+
array_push($attributeNames, (string)$nameValueItem->Name);
|
181 |
+
}
|
182 |
+
}
|
183 |
+
}
|
184 |
+
}
|
185 |
+
//$this->_debug('attribute names for configurable product:');
|
186 |
+
//$this->_debug($attributeNames);
|
187 |
+
$attributeIDList = array();
|
188 |
+
foreach ($attributeNames as $attributeName)
|
189 |
+
{
|
190 |
+
$attributeName = $utilsHelper->replaceInvalidChars($attributeName);
|
191 |
+
$attribute = $attributeCache->getAttribute($attributeName);
|
192 |
+
|
193 |
+
if (!is_null($attribute))
|
194 |
+
{
|
195 |
+
array_push($attributeIDList, $attribute);
|
196 |
+
}
|
197 |
+
}
|
198 |
+
return $attributeIDList;
|
199 |
+
}
|
200 |
+
|
201 |
+
private function findProductAttributeValue($attributeCode, $variationData)
|
202 |
+
{
|
203 |
+
$productAttributeValues = array();
|
204 |
+
|
205 |
+
foreach ($variationData->VariationSpecifics->NameValueList as $nameValueItem)
|
206 |
+
{
|
207 |
+
if(strcasecmp($nameValueItem->Name, $attributeCode) == 0)
|
208 |
+
{
|
209 |
+
return $nameValueItem->Value;
|
210 |
+
}
|
211 |
+
}
|
212 |
+
}
|
213 |
+
|
214 |
+
private function _debug($message)
|
215 |
+
{
|
216 |
+
Mage::log($message);
|
217 |
+
}
|
218 |
+
}
|
app/code/local/Sandbourne/BulkApi/Helper/Data.php
ADDED
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// This empty class is required in order to be able to create a magento soap role.
|
4 |
+
// Magento throws an error without this class.
|
5 |
+
|
6 |
+
class Sandbourne_BulkApi_Helper_Data extends Mage_Core_Helper_Abstract
|
7 |
+
{
|
8 |
+
public function __construct()
|
9 |
+
{
|
10 |
+
//$this->_debug('Array Helper constructed');
|
11 |
+
}
|
12 |
+
|
13 |
+
public function _debug($message)
|
14 |
+
{
|
15 |
+
Mage::log($message);
|
16 |
+
}
|
17 |
+
}
|
app/code/local/Sandbourne/BulkApi/Helper/Image.php
ADDED
@@ -0,0 +1,119 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Sandbourne_BulkApi_Helper_Image extends Mage_Core_Helper_Abstract
|
4 |
+
{
|
5 |
+
public function __construct()
|
6 |
+
{
|
7 |
+
//$this->_debug('Image Helper constructed');
|
8 |
+
}
|
9 |
+
|
10 |
+
public function setImageList($magentoProduct, $productData, $productResultXMLData)
|
11 |
+
{
|
12 |
+
//$this->_debug('setImageList($magentoProduct, $productData, $productResultXMLData)');
|
13 |
+
$magentoImageList = $magentoProduct['media_gallery']['images'];
|
14 |
+
|
15 |
+
$requiredImagesXMLData = new DOMElement('RequiredImages');
|
16 |
+
$productResultXMLData->appendChild($requiredImagesXMLData);
|
17 |
+
|
18 |
+
$imageIndex = 0;
|
19 |
+
|
20 |
+
foreach ($productData->Images->ImageURL as $espImageUrl)
|
21 |
+
{
|
22 |
+
$image = $this->findImage($espImageUrl, $magentoImageList);
|
23 |
+
|
24 |
+
//if (is_null($image))
|
25 |
+
if ($image == NULL) // For ==; NULL, false, 0, and empty string are equal.
|
26 |
+
{
|
27 |
+
//$this->_debug('$image is_null '.$espImageUrl);
|
28 |
+
// Need to create the image. Add it to the list to return to eSellerPro.
|
29 |
+
// eSellerPro will then download the images and pass the image data to Magento.
|
30 |
+
$requiredImageXMLData = new DOMElement('RequiredImage');
|
31 |
+
$requiredImagesXMLData->appendChild($requiredImageXMLData);
|
32 |
+
|
33 |
+
$requiredImageXMLData->appendChild(new DOMElement('URL', $espImageUrl));
|
34 |
+
$requiredImageXMLData->appendChild(new DOMElement('ImageIndex', $imageIndex));
|
35 |
+
}
|
36 |
+
else
|
37 |
+
{
|
38 |
+
$this->setImagePosition($magentoProduct, $image, $imageIndex);
|
39 |
+
}
|
40 |
+
$imageIndex++;
|
41 |
+
}
|
42 |
+
// Now we have all the images are they in the right order
|
43 |
+
//$this->repositionImages($magentoProduct, $productData);
|
44 |
+
// Set the first immage as the gallery image
|
45 |
+
$this->setFirstImageAsBase($magentoProduct);
|
46 |
+
//$this->_debug($magentoProduct['media_gallery']);
|
47 |
+
}
|
48 |
+
|
49 |
+
public function findImage($espImageUrl, $imageList)
|
50 |
+
{
|
51 |
+
//$this->_debug('findImage:'.$espImageUrl);
|
52 |
+
|
53 |
+
$espFilename = basename($espImageUrl);
|
54 |
+
$espFilename = str_replace('%', '_', $espFilename);
|
55 |
+
|
56 |
+
$pathInfo = pathinfo($espFilename);
|
57 |
+
|
58 |
+
$imagePattern = '/'.$pathInfo['filename'].'[\d_]*\.'.$pathInfo['extension'].'/';
|
59 |
+
//$imagePattern = '/'.$pathInfo['filename'].'_\d+\.'.$pathInfo['extension'].'/';
|
60 |
+
foreach ($imageList as $image)
|
61 |
+
{
|
62 |
+
//$this->_debug('looking at '.$image['file']);
|
63 |
+
if (preg_match($imagePattern, $image['file']) === 1)
|
64 |
+
{
|
65 |
+
//$this->_debug('found '.$espFilename);
|
66 |
+
return $image;
|
67 |
+
}
|
68 |
+
}
|
69 |
+
return "";
|
70 |
+
}
|
71 |
+
|
72 |
+
public function setImagePosition(&$magentoProduct, $magentoImage, $newImageIndex)
|
73 |
+
{
|
74 |
+
$mediaGallery = $magentoProduct['media_gallery'];
|
75 |
+
|
76 |
+
$oldImagePosition = $magentoImage['position'];
|
77 |
+
$newImagePosition = $newImageIndex + 1;
|
78 |
+
//$this->_debug('setImagePosition positions('.$oldImagePosition.','.$newImagePosition.')');
|
79 |
+
|
80 |
+
foreach ($magentoProduct['media_gallery']['images'] as $key => $image)
|
81 |
+
{
|
82 |
+
if ($image['file'] === $magentoImage['file'])
|
83 |
+
{
|
84 |
+
//$this->_debug('setting position of index:'.$key.' to '.$newImagePosition);
|
85 |
+
$mediaGallery['images'][$key]['position'] = $newImagePosition;
|
86 |
+
break;
|
87 |
+
}
|
88 |
+
//$this->_debug('iterating at '.$image['file'].' at position:'.$image['position']);
|
89 |
+
}
|
90 |
+
$magentoProduct['media_gallery'] = $mediaGallery;
|
91 |
+
//$this->_debug($magentoImageList);
|
92 |
+
}
|
93 |
+
|
94 |
+
private function setFirstImageAsBase($product)
|
95 |
+
{
|
96 |
+
// Make sure the first image is used for the base, small and thumbnail images.
|
97 |
+
//$this->_debug('setFirstImageAsBase($product)');
|
98 |
+
$mediaGallery = $product->getMediaGallery();
|
99 |
+
|
100 |
+
if (isset($mediaGallery['images']))
|
101 |
+
{
|
102 |
+
foreach ($mediaGallery['images'] as $galleryImage)
|
103 |
+
{
|
104 |
+
if ($galleryImage['position'] === 1)
|
105 |
+
{
|
106 |
+
$product['image'] = $galleryImage['file'];
|
107 |
+
$product['small_image'] = $galleryImage['file'];
|
108 |
+
$product['thumbnail'] = $galleryImage['file'];
|
109 |
+
break;
|
110 |
+
}
|
111 |
+
}
|
112 |
+
}
|
113 |
+
}
|
114 |
+
|
115 |
+
public function _debug($message)
|
116 |
+
{
|
117 |
+
Mage::log($message);
|
118 |
+
}
|
119 |
+
}
|
app/code/local/Sandbourne/BulkApi/Helper/RelatedProducts.php
ADDED
@@ -0,0 +1,43 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Related Products Helper Class, for setting the associated website for the current product.
|
5 |
+
*/
|
6 |
+
|
7 |
+
class Sandbourne_BulkApi_Helper_RelatedProducts extends Mage_Core_Helper_Abstract
|
8 |
+
{
|
9 |
+
|
10 |
+
public function __construct()
|
11 |
+
{
|
12 |
+
//$this->_debug('Related Products Helper constructed');
|
13 |
+
}
|
14 |
+
|
15 |
+
public function getRelatedProducts($productData)
|
16 |
+
{
|
17 |
+
//$this->_debug('getRelatedProducts($productData)');
|
18 |
+
$relatedProductsList = array();
|
19 |
+
$elementCount = 0;
|
20 |
+
|
21 |
+
if (isset($productData->RelatedProducts))
|
22 |
+
{
|
23 |
+
foreach ($productData->RelatedProducts->RelatedStockNumber as $relatedStockNumber)
|
24 |
+
{
|
25 |
+
$searchStockNumber = (string)$relatedStockNumber[0];
|
26 |
+
$relatedProductID = Mage::getModel('catalog/product')->getIdBySku($searchStockNumber);
|
27 |
+
|
28 |
+
if (!empty($relatedProductID))
|
29 |
+
{
|
30 |
+
$relatedProductsList[(string)$relatedProductID] = array('position' => (string)$elementCount++);
|
31 |
+
}
|
32 |
+
}
|
33 |
+
}
|
34 |
+
//$this->_debug($productData->RelatedProducts->RelatedStockNumber);
|
35 |
+
//$this->_debug($relatedProductsList);
|
36 |
+
return $relatedProductsList;
|
37 |
+
}
|
38 |
+
|
39 |
+
private function _debug($message)
|
40 |
+
{
|
41 |
+
Mage::log($message);
|
42 |
+
}
|
43 |
+
}
|
app/code/local/Sandbourne/BulkApi/Helper/TestData.php
ADDED
@@ -0,0 +1,561 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* TestData Helper Class.
|
5 |
+
*/
|
6 |
+
|
7 |
+
class Sandbourne_BulkApi_Helper_TestData extends Mage_Core_Helper_Abstract
|
8 |
+
{
|
9 |
+
|
10 |
+
public function __construct()
|
11 |
+
{
|
12 |
+
//$this->_debug('Test Data Helper constructed');
|
13 |
+
}
|
14 |
+
|
15 |
+
public function loadTestData()
|
16 |
+
{
|
17 |
+
/*
|
18 |
+
* Insert the below code between lines 18 & 19 in FullProduct Api.php
|
19 |
+
* // Testing XML
|
20 |
+
* // Comment these lines out if no testing is required.
|
21 |
+
* $utils = Mage::helper('bulkapi/testData');
|
22 |
+
* $productXML = $utils->loadTestData();
|
23 |
+
* $this->_debug($productXML);
|
24 |
+
* // Testing XML
|
25 |
+
*/
|
26 |
+
|
27 |
+
$testData = '<?xml version="1.0" encoding="UTF-8"?><FullProductsUpdate batch="69" version="1.0">
|
28 |
+
<Product>
|
29 |
+
<StockNumber>Ave</StockNumber>
|
30 |
+
<SupplierSKU/>
|
31 |
+
<InternalSKU/>
|
32 |
+
<SKUType>Master</SKUType>
|
33 |
+
<MasterStockNumber/>
|
34 |
+
<IsActive>Y</IsActive>
|
35 |
+
<Dropship>N</Dropship>
|
36 |
+
<ExternalStoreView/>
|
37 |
+
<Title><![CDATA[Aviator Sunglasses Fashion 80s Retro Style Designer Shades UV400 Lens Unisex]]></Title>
|
38 |
+
<Subtitle><![CDATA[**Many Colours Available - UK Seller - Fast Dispatch**]]></Subtitle>
|
39 |
+
<WebsiteTitle/>
|
40 |
+
<AlternativeWebsiteTitle/>
|
41 |
+
<ListingTitle><![CDATA[Aviator Sunglasses Fashion 80s Retro Style Designer Shades UV400 Lens Unisex]]></ListingTitle>
|
42 |
+
<NewRelease>N</NewRelease>
|
43 |
+
<OnSale>N</OnSale>
|
44 |
+
<SalePrice>0.0</SalePrice>
|
45 |
+
<StockLevel>0</StockLevel>
|
46 |
+
<MinOrderQty>0</MinOrderQty>
|
47 |
+
<SellPrice>3.99</SellPrice>
|
48 |
+
<TaxCode>S</TaxCode>
|
49 |
+
<TaxRate>20.0</TaxRate>
|
50 |
+
<RRP>14.99</RRP>
|
51 |
+
<CostEach>0.0</CostEach>
|
52 |
+
<ShippingCost>0.0</ShippingCost>
|
53 |
+
<ShortDescription/>
|
54 |
+
<Description><![CDATA[<ul>
|
55 |
+
<li>
|
56 |
+
Aviator sunglasses are the must have fashion accessory of the summer.
|
57 |
+
Ideal for day to day wearing, holidays and festivals too!
|
58 |
+
</li>
|
59 |
+
|
60 |
+
<li>
|
61 |
+
We have a large range of colours, so select your favourites from the
|
62 |
+
drop down list
|
63 |
+
</li>
|
64 |
+
|
65 |
+
<li>
|
66 |
+
All sunglassses offer full UV400 protection
|
67 |
+
</li>
|
68 |
+
|
69 |
+
<li>
|
70 |
+
These are metal frames
|
71 |
+
</li>
|
72 |
+
|
73 |
+
<li>
|
74 |
+
Sunglasses are one size fits all
|
75 |
+
</li>
|
76 |
+
|
77 |
+
<li>
|
78 |
+
If you have any questions, please email sales@retailzone.com
|
79 |
+
</li>
|
80 |
+
|
81 |
+
</ul>]]></Description>
|
82 |
+
<Description2><![CDATA[<ul>
|
83 |
+
<li>
|
84 |
+
Aviator sunglasses are the must have fashion accessory of the summer.
|
85 |
+
Ideal for day to day wearing, holidays and festivals too!
|
86 |
+
</li>
|
87 |
+
|
88 |
+
<li>
|
89 |
+
We have a large range of colours, so select your favourites from the
|
90 |
+
drop down list
|
91 |
+
</li>
|
92 |
+
|
93 |
+
<li>
|
94 |
+
All sunglassses offer full UV400 protection
|
95 |
+
</li>
|
96 |
+
|
97 |
+
<li>
|
98 |
+
These are metal frames
|
99 |
+
</li>
|
100 |
+
|
101 |
+
<li>
|
102 |
+
Sunglasses are one size fits all
|
103 |
+
</li>
|
104 |
+
|
105 |
+
<li>
|
106 |
+
If you have any questions, please email sales@retailzone.com
|
107 |
+
</li>
|
108 |
+
|
109 |
+
</ul>
|
110 |
+
|
111 |
+
|
112 |
+
|
113 |
+
|
114 |
+
|
115 |
+
2]]></Description2>
|
116 |
+
<Description3><![CDATA[<ul>
|
117 |
+
<li>
|
118 |
+
Aviator sunglasses are the must have fashion accessory of the summer.
|
119 |
+
Ideal for day to day wearing, holidays and festivals too!
|
120 |
+
</li>
|
121 |
+
|
122 |
+
<li>
|
123 |
+
We have a large range of colours, so select your favourites from the
|
124 |
+
drop down list
|
125 |
+
</li>
|
126 |
+
|
127 |
+
<li>
|
128 |
+
All sunglassses offer full UV400 protection
|
129 |
+
</li>
|
130 |
+
|
131 |
+
<li>
|
132 |
+
These are metal frames
|
133 |
+
</li>
|
134 |
+
|
135 |
+
<li>
|
136 |
+
Sunglasses are one size fits all
|
137 |
+
</li>
|
138 |
+
|
139 |
+
<li>
|
140 |
+
If you have any questions, please email sales@retailzone.com
|
141 |
+
</li>
|
142 |
+
|
143 |
+
</ul>
|
144 |
+
|
145 |
+
|
146 |
+
|
147 |
+
|
148 |
+
|
149 |
+
3]]></Description3>
|
150 |
+
<Description4><![CDATA[<ul>
|
151 |
+
<li>
|
152 |
+
Aviator sunglasses are the must have fashion accessory of the summer.
|
153 |
+
Ideal for day to day wearing, holidays and festivals too!
|
154 |
+
</li>
|
155 |
+
|
156 |
+
<li>
|
157 |
+
We have a large range of colours, so select your favourites from the
|
158 |
+
drop down list
|
159 |
+
</li>
|
160 |
+
|
161 |
+
<li>
|
162 |
+
All sunglassses offer full UV400 protection
|
163 |
+
</li>
|
164 |
+
|
165 |
+
<li>
|
166 |
+
These are metal frames
|
167 |
+
</li>
|
168 |
+
|
169 |
+
<li>
|
170 |
+
Sunglasses are one size fits all
|
171 |
+
</li>
|
172 |
+
|
173 |
+
<li>
|
174 |
+
If you have any questions, please email sales@retailzone.com
|
175 |
+
</li>
|
176 |
+
|
177 |
+
</ul>
|
178 |
+
|
179 |
+
|
180 |
+
|
181 |
+
|
182 |
+
|
183 |
+
4]]></Description4>
|
184 |
+
<Description5><![CDATA[<ul>
|
185 |
+
<li>
|
186 |
+
Aviator sunglasses are the must have fashion accessory of the summer.
|
187 |
+
Ideal for day to day wearing, holidays and festivals too!
|
188 |
+
</li>
|
189 |
+
|
190 |
+
<li>
|
191 |
+
We have a large range of colours, so select your favourites from the
|
192 |
+
drop down list
|
193 |
+
</li>
|
194 |
+
|
195 |
+
<li>
|
196 |
+
All sunglassses offer full UV400 protection
|
197 |
+
</li>
|
198 |
+
|
199 |
+
<li>
|
200 |
+
These are metal frames
|
201 |
+
</li>
|
202 |
+
|
203 |
+
<li>
|
204 |
+
Sunglasses are one size fits all
|
205 |
+
</li>
|
206 |
+
|
207 |
+
<li>
|
208 |
+
If you have any questions, please email sales@retailzone.com
|
209 |
+
</li>
|
210 |
+
|
211 |
+
</ul>
|
212 |
+
|
213 |
+
|
214 |
+
|
215 |
+
|
216 |
+
|
217 |
+
5]]></Description5>
|
218 |
+
<MetaDescription/>
|
219 |
+
<Images>
|
220 |
+
<ImageURL>http://images.esellerpro.com/2316/I/269/78/Aviators.jpg</ImageURL>
|
221 |
+
</Images>
|
222 |
+
<Weight unit="g">0.0</Weight>
|
223 |
+
<Width unit="(mm)">0</Width>
|
224 |
+
<Height unit="(mm)">0</Height>
|
225 |
+
<Depth unit="(mm)">0</Depth>
|
226 |
+
<UPC/>
|
227 |
+
<AllowPreOrder>N</AllowPreOrder>
|
228 |
+
<Keywords/>
|
229 |
+
<Publisher/>
|
230 |
+
<ISBN/>
|
231 |
+
<Notes/>
|
232 |
+
<Source>stevejames</Source>
|
233 |
+
<Category/>
|
234 |
+
<ProductCategories>
|
235 |
+
<ProductCategory><![CDATA[ChildrensFancyDressNet>2014 - RetailZone>Clothing Accessories>Sunglasses>Aviator]]></ProductCategory>
|
236 |
+
</ProductCategories>
|
237 |
+
<Supplier>Agent (Juny)</Supplier>
|
238 |
+
<ShowInHome>N</ShowInHome>
|
239 |
+
<FreeShipping>N</FreeShipping>
|
240 |
+
<StarItem>N</StarItem>
|
241 |
+
<FeatureProduct>N</FeatureProduct>
|
242 |
+
<Feature2>N</Feature2>
|
243 |
+
<Feature3>N</Feature3>
|
244 |
+
<VideoName/>
|
245 |
+
<ShippingTemplate/>
|
246 |
+
<CustomGroups>
|
247 |
+
<CustomGroup groupName="0">
|
248 |
+
<CustomFields/>
|
249 |
+
</CustomGroup>
|
250 |
+
<CustomGroup groupName="ebay item specifics">
|
251 |
+
<CustomFields>
|
252 |
+
<NameValueList>
|
253 |
+
<Name>Type</Name>
|
254 |
+
<Value><![CDATA[Aviator Sunglasses]]></Value>
|
255 |
+
</NameValueList>
|
256 |
+
<NameValueList>
|
257 |
+
<Name>Gender</Name>
|
258 |
+
<Value><![CDATA[Unisex - Male - Mens - Female - Ladies]]></Value>
|
259 |
+
</NameValueList>
|
260 |
+
<NameValueList>
|
261 |
+
<Name>Size</Name>
|
262 |
+
<Value><![CDATA[One Size Fits All]]></Value>
|
263 |
+
</NameValueList>
|
264 |
+
<NameValueList>
|
265 |
+
<Name>Theme</Name>
|
266 |
+
<Value><![CDATA[Fashion Designer Style Shades]]></Value>
|
267 |
+
</NameValueList>
|
268 |
+
<NameValueList>
|
269 |
+
<Name>Features</Name>
|
270 |
+
<Value><![CDATA[Metal Frame]]></Value>
|
271 |
+
</NameValueList>
|
272 |
+
<NameValueList>
|
273 |
+
<Name>Lense</Name>
|
274 |
+
<Value><![CDATA[UV400 Protection]]></Value>
|
275 |
+
</NameValueList>
|
276 |
+
</CustomFields>
|
277 |
+
</CustomGroup>
|
278 |
+
<CustomGroup groupName="ExtraFields">
|
279 |
+
<CustomFields/>
|
280 |
+
</CustomGroup>
|
281 |
+
<CustomGroup groupName="FRANCE">
|
282 |
+
<CustomFields/>
|
283 |
+
</CustomGroup>
|
284 |
+
<CustomGroup groupName="GERMANY">
|
285 |
+
<CustomFields/>
|
286 |
+
</CustomGroup>
|
287 |
+
<CustomGroup groupName="ITALY">
|
288 |
+
<CustomFields/>
|
289 |
+
</CustomGroup>
|
290 |
+
<CustomGroup groupName="MVL">
|
291 |
+
<CustomFields/>
|
292 |
+
</CustomGroup>
|
293 |
+
<CustomGroup groupName="No">
|
294 |
+
<CustomFields/>
|
295 |
+
</CustomGroup>
|
296 |
+
<CustomGroup groupName="ProductVariations">
|
297 |
+
<CustomFields/>
|
298 |
+
</CustomGroup>
|
299 |
+
<CustomGroup groupName="SPAIN">
|
300 |
+
<CustomFields/>
|
301 |
+
</CustomGroup>
|
302 |
+
</CustomGroups>
|
303 |
+
<Variations>
|
304 |
+
<Variation>
|
305 |
+
<StockNumber>(L) Bin07 - AveMir</StockNumber>
|
306 |
+
<SellPrice>2.69</SellPrice>
|
307 |
+
<TaxCode>S</TaxCode>
|
308 |
+
<StockLevel>2884</StockLevel>
|
309 |
+
<VariationSpecifics>
|
310 |
+
<NameValueList>
|
311 |
+
<Name>Colour</Name>
|
312 |
+
<Value><![CDATA[Mirror (Silver)]]></Value>
|
313 |
+
</NameValueList>
|
314 |
+
</VariationSpecifics>
|
315 |
+
</Variation>
|
316 |
+
<Variation>
|
317 |
+
<StockNumber>(L) R05-252 - AveBlu</StockNumber>
|
318 |
+
<SellPrice>3.99</SellPrice>
|
319 |
+
<TaxCode>S</TaxCode>
|
320 |
+
<StockLevel>250</StockLevel>
|
321 |
+
<VariationSpecifics>
|
322 |
+
<NameValueList>
|
323 |
+
<Name>Colour</Name>
|
324 |
+
<Value><![CDATA[Blue]]></Value>
|
325 |
+
</NameValueList>
|
326 |
+
</VariationSpecifics>
|
327 |
+
</Variation>
|
328 |
+
<Variation>
|
329 |
+
<StockNumber>(L) Bin13 - AveRed</StockNumber>
|
330 |
+
<SellPrice>3.99</SellPrice>
|
331 |
+
<TaxCode>S</TaxCode>
|
332 |
+
<StockLevel>14</StockLevel>
|
333 |
+
<VariationSpecifics>
|
334 |
+
<NameValueList>
|
335 |
+
<Name>Colour</Name>
|
336 |
+
<Value><![CDATA[Red]]></Value>
|
337 |
+
</NameValueList>
|
338 |
+
</VariationSpecifics>
|
339 |
+
</Variation>
|
340 |
+
<Variation>
|
341 |
+
<StockNumber>(L) R05-251 - AvePnk</StockNumber>
|
342 |
+
<SellPrice>2.89</SellPrice>
|
343 |
+
<TaxCode>S</TaxCode>
|
344 |
+
<StockLevel>593</StockLevel>
|
345 |
+
<VariationSpecifics>
|
346 |
+
<NameValueList>
|
347 |
+
<Name>Colour</Name>
|
348 |
+
<Value><![CDATA[Pink]]></Value>
|
349 |
+
</NameValueList>
|
350 |
+
</VariationSpecifics>
|
351 |
+
</Variation>
|
352 |
+
<Variation>
|
353 |
+
<StockNumber>(L) R06-137 - AveBlk</StockNumber>
|
354 |
+
<SellPrice>3.99</SellPrice>
|
355 |
+
<TaxCode>S</TaxCode>
|
356 |
+
<StockLevel>54</StockLevel>
|
357 |
+
<VariationSpecifics>
|
358 |
+
<NameValueList>
|
359 |
+
<Name>Colour</Name>
|
360 |
+
<Value><![CDATA[Black]]></Value>
|
361 |
+
</NameValueList>
|
362 |
+
</VariationSpecifics>
|
363 |
+
</Variation>
|
364 |
+
<Variation>
|
365 |
+
<StockNumber>(L) Bin14 - AveBrown</StockNumber>
|
366 |
+
<SellPrice>3.99</SellPrice>
|
367 |
+
<TaxCode>S</TaxCode>
|
368 |
+
<StockLevel>193</StockLevel>
|
369 |
+
<VariationSpecifics>
|
370 |
+
<NameValueList>
|
371 |
+
<Name>Colour</Name>
|
372 |
+
<Value><![CDATA[Brown]]></Value>
|
373 |
+
</NameValueList>
|
374 |
+
</VariationSpecifics>
|
375 |
+
</Variation>
|
376 |
+
<Variation>
|
377 |
+
<StockNumber>(L) Bin04 - AveGold</StockNumber>
|
378 |
+
<SellPrice>2.89</SellPrice>
|
379 |
+
<TaxCode>S</TaxCode>
|
380 |
+
<StockLevel>1332</StockLevel>
|
381 |
+
<VariationSpecifics>
|
382 |
+
<NameValueList>
|
383 |
+
<Name>Colour</Name>
|
384 |
+
<Value><![CDATA[Gold]]></Value>
|
385 |
+
</NameValueList>
|
386 |
+
</VariationSpecifics>
|
387 |
+
</Variation>
|
388 |
+
<Variation>
|
389 |
+
<StockNumber>(L) AvePouch</StockNumber>
|
390 |
+
<SellPrice>0.99</SellPrice>
|
391 |
+
<TaxCode>S</TaxCode>
|
392 |
+
<StockLevel>22</StockLevel>
|
393 |
+
<VariationSpecifics>
|
394 |
+
<NameValueList>
|
395 |
+
<Name>Colour</Name>
|
396 |
+
<Value><![CDATA[Cloth Case]]></Value>
|
397 |
+
</NameValueList>
|
398 |
+
</VariationSpecifics>
|
399 |
+
</Variation>
|
400 |
+
<Variation>
|
401 |
+
<StockNumber>(L) R06-013 - AveWht</StockNumber>
|
402 |
+
<SellPrice>3.99</SellPrice>
|
403 |
+
<TaxCode>S</TaxCode>
|
404 |
+
<StockLevel>272</StockLevel>
|
405 |
+
<VariationSpecifics>
|
406 |
+
<NameValueList>
|
407 |
+
<Name>Colour</Name>
|
408 |
+
<Value><![CDATA[White]]></Value>
|
409 |
+
</NameValueList>
|
410 |
+
</VariationSpecifics>
|
411 |
+
</Variation>
|
412 |
+
<Variation>
|
413 |
+
<StockNumber>(L) R22-527 - AveBlkBluMir</StockNumber>
|
414 |
+
<SellPrice>3.99</SellPrice>
|
415 |
+
<TaxCode>S</TaxCode>
|
416 |
+
<StockLevel>1190</StockLevel>
|
417 |
+
<VariationSpecifics>
|
418 |
+
<NameValueList>
|
419 |
+
<Name>Colour</Name>
|
420 |
+
<Value><![CDATA[Black Frame Blue Mirror Lense]]></Value>
|
421 |
+
</NameValueList>
|
422 |
+
</VariationSpecifics>
|
423 |
+
</Variation>
|
424 |
+
<Variation>
|
425 |
+
<StockNumber>(L) R22-528 - AveBlkMir</StockNumber>
|
426 |
+
<SellPrice>3.99</SellPrice>
|
427 |
+
<TaxCode>S</TaxCode>
|
428 |
+
<StockLevel>66</StockLevel>
|
429 |
+
<VariationSpecifics>
|
430 |
+
<NameValueList>
|
431 |
+
<Name>Colour</Name>
|
432 |
+
<Value><![CDATA[Black Frame Mirror Lense]]></Value>
|
433 |
+
</NameValueList>
|
434 |
+
</VariationSpecifics>
|
435 |
+
</Variation>
|
436 |
+
<Variation>
|
437 |
+
<StockNumber>(L) R22-529 - AveGldMir</StockNumber>
|
438 |
+
<SellPrice>3.99</SellPrice>
|
439 |
+
<TaxCode>S</TaxCode>
|
440 |
+
<StockLevel>15</StockLevel>
|
441 |
+
<VariationSpecifics>
|
442 |
+
<NameValueList>
|
443 |
+
<Name>Colour</Name>
|
444 |
+
<Value><![CDATA[Gold Frame Mirror Lense]]></Value>
|
445 |
+
</NameValueList>
|
446 |
+
</VariationSpecifics>
|
447 |
+
</Variation>
|
448 |
+
<Variation>
|
449 |
+
<StockNumber>(L) R22-530 - AvePnkBlk</StockNumber>
|
450 |
+
<SellPrice>3.99</SellPrice>
|
451 |
+
<TaxCode>S</TaxCode>
|
452 |
+
<StockLevel>90</StockLevel>
|
453 |
+
<VariationSpecifics>
|
454 |
+
<NameValueList>
|
455 |
+
<Name>Colour</Name>
|
456 |
+
<Value><![CDATA[Pink Frame Black Tint Lense]]></Value>
|
457 |
+
</NameValueList>
|
458 |
+
</VariationSpecifics>
|
459 |
+
</Variation>
|
460 |
+
<Variation>
|
461 |
+
<StockNumber>(L) R22-531 - AveWhtMir</StockNumber>
|
462 |
+
<SellPrice>3.99</SellPrice>
|
463 |
+
<TaxCode>S</TaxCode>
|
464 |
+
<StockLevel>98</StockLevel>
|
465 |
+
<VariationSpecifics>
|
466 |
+
<NameValueList>
|
467 |
+
<Name>Colour</Name>
|
468 |
+
<Value><![CDATA[White Frame Mirror Lense]]></Value>
|
469 |
+
</NameValueList>
|
470 |
+
</VariationSpecifics>
|
471 |
+
</Variation>
|
472 |
+
<Variation>
|
473 |
+
<StockNumber>(L) R22-532 - AvePur</StockNumber>
|
474 |
+
<SellPrice>2.89</SellPrice>
|
475 |
+
<TaxCode>S</TaxCode>
|
476 |
+
<StockLevel>593</StockLevel>
|
477 |
+
<VariationSpecifics>
|
478 |
+
<NameValueList>
|
479 |
+
<Name>Colour</Name>
|
480 |
+
<Value><![CDATA[Purple]]></Value>
|
481 |
+
</NameValueList>
|
482 |
+
</VariationSpecifics>
|
483 |
+
</Variation>
|
484 |
+
<Variation>
|
485 |
+
<StockNumber>(L) R22-533 - AveOra</StockNumber>
|
486 |
+
<SellPrice>2.89</SellPrice>
|
487 |
+
<TaxCode>S</TaxCode>
|
488 |
+
<StockLevel>0</StockLevel>
|
489 |
+
<VariationSpecifics>
|
490 |
+
<NameValueList>
|
491 |
+
<Name>Colour</Name>
|
492 |
+
<Value><![CDATA[Orange]]></Value>
|
493 |
+
</NameValueList>
|
494 |
+
</VariationSpecifics>
|
495 |
+
</Variation>
|
496 |
+
<Variation>
|
497 |
+
<StockNumber>(L) R22-534 - AveSilBlk</StockNumber>
|
498 |
+
<SellPrice>3.69</SellPrice>
|
499 |
+
<TaxCode>S</TaxCode>
|
500 |
+
<StockLevel>450</StockLevel>
|
501 |
+
<VariationSpecifics>
|
502 |
+
<NameValueList>
|
503 |
+
<Name>Colour</Name>
|
504 |
+
<Value><![CDATA[Silver Frame Black Tint Lense]]></Value>
|
505 |
+
</NameValueList>
|
506 |
+
</VariationSpecifics>
|
507 |
+
</Variation>
|
508 |
+
<Variation>
|
509 |
+
<StockNumber>(L) R22-535 - AveYel</StockNumber>
|
510 |
+
<SellPrice>2.89</SellPrice>
|
511 |
+
<TaxCode>S</TaxCode>
|
512 |
+
<StockLevel>10</StockLevel>
|
513 |
+
<VariationSpecifics>
|
514 |
+
<NameValueList>
|
515 |
+
<Name>Colour</Name>
|
516 |
+
<Value><![CDATA[Yellow]]></Value>
|
517 |
+
</NameValueList>
|
518 |
+
</VariationSpecifics>
|
519 |
+
</Variation>
|
520 |
+
<Variation>
|
521 |
+
<StockNumber>(L) R22-536 - AvePnkMir</StockNumber>
|
522 |
+
<SellPrice>3.99</SellPrice>
|
523 |
+
<TaxCode>S</TaxCode>
|
524 |
+
<StockLevel>60</StockLevel>
|
525 |
+
<VariationSpecifics>
|
526 |
+
<NameValueList>
|
527 |
+
<Name>Colour</Name>
|
528 |
+
<Value><![CDATA[Pink Frame Mirror Lense]]></Value>
|
529 |
+
</NameValueList>
|
530 |
+
</VariationSpecifics>
|
531 |
+
</Variation>
|
532 |
+
<Variation>
|
533 |
+
<StockNumber>(L) Bin03 - AveBluMir</StockNumber>
|
534 |
+
<SellPrice>3.99</SellPrice>
|
535 |
+
<TaxCode>S</TaxCode>
|
536 |
+
<StockLevel>1492</StockLevel>
|
537 |
+
<VariationSpecifics>
|
538 |
+
<NameValueList>
|
539 |
+
<Name>Colour</Name>
|
540 |
+
<Value><![CDATA[Silver Frame Blue Mirror Lense]]></Value>
|
541 |
+
</NameValueList>
|
542 |
+
</VariationSpecifics>
|
543 |
+
</Variation>
|
544 |
+
</Variations>
|
545 |
+
<UseVariations>Y</UseVariations>
|
546 |
+
<RelatedProducts/>
|
547 |
+
<SimilarProducts/>
|
548 |
+
<StoreView/>
|
549 |
+
<AttributeSet/>
|
550 |
+
<Ignore>N</Ignore>
|
551 |
+
<IgnoreImages>N</IgnoreImages>
|
552 |
+
<IgnoreCategories>N</IgnoreCategories>
|
553 |
+
<IgnoreDescription>N</IgnoreDescription>
|
554 |
+
<IgnoreCustomFields>N</IgnoreCustomFields>
|
555 |
+
<UseCustomGroups>ebay item specifics</UseCustomGroups>
|
556 |
+
</Product>
|
557 |
+
</FullProductsUpdate>';
|
558 |
+
|
559 |
+
return $testData;
|
560 |
+
}
|
561 |
+
}
|
app/code/local/Sandbourne/BulkApi/Helper/Utils.php
ADDED
@@ -0,0 +1,70 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Utils Helper Class, collection of basic utilities.
|
5 |
+
*/
|
6 |
+
|
7 |
+
class Sandbourne_BulkApi_Helper_Utils extends Mage_Core_Helper_Abstract
|
8 |
+
{
|
9 |
+
|
10 |
+
public function __construct()
|
11 |
+
{
|
12 |
+
//$this->_debug('Utils Helper constructed');
|
13 |
+
}
|
14 |
+
|
15 |
+
public function isAttributeReserved($attribute)
|
16 |
+
{
|
17 |
+
//$this->_debug(">> isAttributeReserved");
|
18 |
+
|
19 |
+
$RESERVED_ATTRIBUTES = array("SITE:");
|
20 |
+
|
21 |
+
$retVal = false;
|
22 |
+
foreach ($RESERVED_ATTRIBUTES as $string)
|
23 |
+
{
|
24 |
+
if (strpos($attribute, $string) !== false)
|
25 |
+
{
|
26 |
+
$retVal = true;
|
27 |
+
}
|
28 |
+
}
|
29 |
+
return $retVal;
|
30 |
+
}
|
31 |
+
|
32 |
+
public function replaceInvalidChars($stringItem)
|
33 |
+
{
|
34 |
+
//$this->_debug(">> replaceInvalidChars");
|
35 |
+
|
36 |
+
$INVALID_CHARACTERS = array(" ", ":", "/", ".");
|
37 |
+
$REPLACEMENT_CHARACTER = "_";
|
38 |
+
|
39 |
+
foreach ($INVALID_CHARACTERS as $char)
|
40 |
+
{
|
41 |
+
$stringItem = str_replace($char, $REPLACEMENT_CHARACTER, $stringItem);
|
42 |
+
}
|
43 |
+
|
44 |
+
return $stringItem;
|
45 |
+
}
|
46 |
+
|
47 |
+
public function isCustomFieldValid($stringItem)
|
48 |
+
{
|
49 |
+
//$this->_debug(">> isCustomFieldValid");
|
50 |
+
|
51 |
+
// The rule for Magento custom fields is to use only letters (a-z), numbers (0-9) or underscore(_)
|
52 |
+
// in the field name and the first character should be a letter.
|
53 |
+
// As we are replacing some invalid characters (:./) with an underscore,
|
54 |
+
// we can include these into the regular expression.
|
55 |
+
|
56 |
+
$retVal = FALSE;
|
57 |
+
|
58 |
+
if (preg_match("/^[A-Z a-z][A-Z a-z 0-9 _ : \/ .]*$/", $stringItem) > 0)
|
59 |
+
{
|
60 |
+
$retVal = TRUE;
|
61 |
+
}
|
62 |
+
|
63 |
+
return $retVal;
|
64 |
+
}
|
65 |
+
|
66 |
+
private function _debug($message)
|
67 |
+
{
|
68 |
+
Mage::log($message);
|
69 |
+
}
|
70 |
+
}
|
app/code/local/Sandbourne/BulkApi/Helper/Website.php
ADDED
@@ -0,0 +1,120 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Website Helper Class, for setting the associated website for the current product.
|
5 |
+
*/
|
6 |
+
|
7 |
+
class Sandbourne_BulkApi_Helper_Website extends Mage_Core_Helper_Abstract
|
8 |
+
{
|
9 |
+
//const MAGENTO_CUSTOM_GROUP_NAME = "Magento";
|
10 |
+
|
11 |
+
public function __construct()
|
12 |
+
{
|
13 |
+
//$this->_debug('Website Helper constructed');
|
14 |
+
}
|
15 |
+
|
16 |
+
public function getProductWebsiteIDs($productData)
|
17 |
+
{
|
18 |
+
$currentWebsites = $this->getCurrentWebsites();
|
19 |
+
$productWebsites = $this->getProductWebsites($productData);
|
20 |
+
$result = array();
|
21 |
+
|
22 |
+
foreach ($productWebsites as $website)
|
23 |
+
{
|
24 |
+
if (array_search($website, $currentWebsites, true))
|
25 |
+
{
|
26 |
+
array_push($result, array_search($website, $currentWebsites, true));
|
27 |
+
}
|
28 |
+
}
|
29 |
+
if (empty($result))
|
30 |
+
{
|
31 |
+
array_push($result, 1);
|
32 |
+
}
|
33 |
+
return $result;
|
34 |
+
}
|
35 |
+
|
36 |
+
private function getCurrentWebsites()
|
37 |
+
{
|
38 |
+
$currentWebsites = array();
|
39 |
+
|
40 |
+
foreach (Mage::app()->getWebsites() as $website)
|
41 |
+
{
|
42 |
+
// Remove the whitespace from the magento website names to match the whitespace removed from the XML.
|
43 |
+
$currentWebsites[$website->getID()] = str_replace(" ", "", $website->getName());
|
44 |
+
}
|
45 |
+
return $currentWebsites;
|
46 |
+
}
|
47 |
+
|
48 |
+
private function getProductWebsites($productData)
|
49 |
+
{
|
50 |
+
$result = array();
|
51 |
+
|
52 |
+
if (isset($productData->CustomGroups))
|
53 |
+
{
|
54 |
+
$siteCustomFields = array();
|
55 |
+
|
56 |
+
$lookUseCustomGroups = trim($productData->UseCustomGroups);
|
57 |
+
if (!$lookUseCustomGroups)
|
58 |
+
{
|
59 |
+
$lookUseCustomGroups = "Magento";
|
60 |
+
}
|
61 |
+
$lookUseCustomGroups = explode(',', $lookUseCustomGroups);
|
62 |
+
|
63 |
+
foreach ($productData->CustomGroups->CustomGroup as $customGroup)
|
64 |
+
{
|
65 |
+
// Only check for Custom Groups that have been specified in the field "Use Custom Groups".
|
66 |
+
// If no Custom Group has been defined, use the default group.
|
67 |
+
foreach ($lookUseCustomGroups as $lookUseCustomGroup)
|
68 |
+
{
|
69 |
+
if ((string)$customGroup['groupName'] === trim($lookUseCustomGroup))
|
70 |
+
{
|
71 |
+
$siteCustomFields = $siteCustomFields + $this->getSiteCustomFields($customGroup);
|
72 |
+
}
|
73 |
+
}
|
74 |
+
//$siteCustomFields = $siteCustomFields + $this->getSiteCustomFields($customGroup);
|
75 |
+
}
|
76 |
+
$productWebsites = $this->getAllProductWebsites($siteCustomFields);
|
77 |
+
if (isset($productWebsites))
|
78 |
+
{
|
79 |
+
$result = $productWebsites;
|
80 |
+
}
|
81 |
+
}
|
82 |
+
return $result;
|
83 |
+
}
|
84 |
+
|
85 |
+
private function getSiteCustomFields($customGroup)
|
86 |
+
{
|
87 |
+
$siteCustomFields = array();
|
88 |
+
|
89 |
+
foreach ($customGroup->CustomFields->NameValueList as $nameValueList)
|
90 |
+
{
|
91 |
+
if (!empty($nameValueList))
|
92 |
+
{
|
93 |
+
if (substr($nameValueList->Name, 0, 5) === "SITE:")
|
94 |
+
{
|
95 |
+
array_push($siteCustomFields, $nameValueList);
|
96 |
+
}
|
97 |
+
}
|
98 |
+
}
|
99 |
+
return $siteCustomFields;
|
100 |
+
}
|
101 |
+
|
102 |
+
private function getAllProductWebsites($siteCustomFields)
|
103 |
+
{
|
104 |
+
$productWebsites = array();
|
105 |
+
|
106 |
+
foreach ($siteCustomFields as $nameValue)
|
107 |
+
{
|
108 |
+
if (strtolower((string)$nameValue->Value) === "y")
|
109 |
+
{
|
110 |
+
array_push($productWebsites, str_replace("SITE:", "", $nameValue->Name));
|
111 |
+
}
|
112 |
+
}
|
113 |
+
return $productWebsites;
|
114 |
+
}
|
115 |
+
|
116 |
+
private function _debug($message)
|
117 |
+
{
|
118 |
+
Mage::log($message);
|
119 |
+
}
|
120 |
+
}
|
app/code/local/Sandbourne/BulkApi/Model/FullImage/Api.php
ADDED
@@ -0,0 +1,91 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Sandbourne_BulkApi_Model_FullImage_Api extends Mage_Api_Model_Resource_Abstract
|
4 |
+
{
|
5 |
+
public function __construct()
|
6 |
+
{
|
7 |
+
//$this->_debug('FullImage constructed');
|
8 |
+
}
|
9 |
+
|
10 |
+
public function update($productXML)
|
11 |
+
{
|
12 |
+
$productXMLData = simplexml_load_string($productXML);
|
13 |
+
$ioAdapter = new Varien_Io_File();
|
14 |
+
$imageHelper = Mage::helper('bulkapi/image');
|
15 |
+
|
16 |
+
foreach ($productXMLData as $imageData)
|
17 |
+
{
|
18 |
+
$data = array();
|
19 |
+
$productID = Mage::getModel('catalog/product')->getIdBySku($imageData->stockNumber);
|
20 |
+
//$this->_debug($imageData->url);
|
21 |
+
|
22 |
+
if ($productID > 0)
|
23 |
+
{
|
24 |
+
$product = Mage::getModel('catalog/product')->load($productID);
|
25 |
+
$mediaGallery = $product['media_gallery'];
|
26 |
+
$imageFound = $imageHelper->findImage($imageData->url, $mediaGallery['images']);
|
27 |
+
|
28 |
+
if (!$imageFound)
|
29 |
+
{
|
30 |
+
//$this->_debug('FullImage API - New Image');
|
31 |
+
$fileContent = @base64_decode((string)$imageData->content, true);
|
32 |
+
$tmpDirectory = Mage::getBaseDir('var') . DS . 'api' . DS . $this->_getSession()->getSessionId();
|
33 |
+
|
34 |
+
$ioAdapter->checkAndCreateFolder($tmpDirectory);
|
35 |
+
$ioAdapter->open(array('path'=>$tmpDirectory));
|
36 |
+
|
37 |
+
if (!$fileContent)
|
38 |
+
{
|
39 |
+
//$this->_debug('Invalid image data');
|
40 |
+
}
|
41 |
+
|
42 |
+
$espFilename = basename($imageData->url);
|
43 |
+
|
44 |
+
// Write image file
|
45 |
+
@file_put_contents($tmpDirectory . DS . $espFilename, $fileContent);
|
46 |
+
|
47 |
+
$attributes = $product->getTypeInstance(true)->getSetAttributes($product);
|
48 |
+
$mediaGalleryObj = $attributes['media_gallery'];
|
49 |
+
|
50 |
+
// Adding image to gallery (the last parameter for addImage so whether to move the image or not)
|
51 |
+
//$file = $mediaGalleryObj->getBackend()->addImage($product, $tmpDirectory . DS . $espFilename, null, true);
|
52 |
+
$file = $mediaGalleryObj->getBackend()->addImage($product, $tmpDirectory . DS . $espFilename, null, false);
|
53 |
+
|
54 |
+
// Remove temporary directory
|
55 |
+
$ioAdapter->rmdir($tmpDirectory, true);
|
56 |
+
|
57 |
+
$data['label'] = $espFilename;
|
58 |
+
$data['exclude'] = '0';
|
59 |
+
$data['name'] = $espFilename;
|
60 |
+
$data['file'] = $espFilename;
|
61 |
+
|
62 |
+
$index = (string)$imageData->imageIndex;
|
63 |
+
$data['position'] = $index;
|
64 |
+
|
65 |
+
// If this is the first Image for this product then set it as the Image, SmallImage and Thumbnail default.
|
66 |
+
if ($index === '0')
|
67 |
+
{
|
68 |
+
$product->setImage($file);
|
69 |
+
$product->setSmallImage($file);
|
70 |
+
$product->setThumbnail($file);
|
71 |
+
}
|
72 |
+
|
73 |
+
//$data['mime'] = 'image/jpeg';
|
74 |
+
//$data['types'] = array('image', 'small_image', 'thumbnail');
|
75 |
+
$mediaGalleryObj->getBackend()->updateImage($product, $file, $data);
|
76 |
+
$product->save();
|
77 |
+
}
|
78 |
+
else
|
79 |
+
{
|
80 |
+
//$this->_debug('FullImage API - EXISTING Image');
|
81 |
+
$file = $imageFound;
|
82 |
+
}
|
83 |
+
}
|
84 |
+
}
|
85 |
+
}
|
86 |
+
|
87 |
+
public function _debug($message)
|
88 |
+
{
|
89 |
+
Mage::log($message);
|
90 |
+
}
|
91 |
+
}
|
app/code/local/Sandbourne/BulkApi/Model/FullImage/Api/V2.php
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Sandbourne_BulkApi_Model_FullImage_Api_V2 extends Sandbourne_BulkApi_Model_FullImage_Api
|
3 |
+
{
|
4 |
+
public function update($productXML)
|
5 |
+
{
|
6 |
+
return parent::update($productXML);
|
7 |
+
}
|
8 |
+
}
|
9 |
+
|
app/code/local/Sandbourne/BulkApi/Model/FullProduct/Api.php
ADDED
@@ -0,0 +1,213 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Sandbourne_BulkApi_Model_FullProduct_Api extends Mage_Api_Model_Resource_Abstract
|
4 |
+
{
|
5 |
+
public function __construct()
|
6 |
+
{
|
7 |
+
//$this->_debug('FullProduct constructed');
|
8 |
+
}
|
9 |
+
|
10 |
+
public function version()
|
11 |
+
{
|
12 |
+
//return "1.0.0.6"; // 20140604
|
13 |
+
return "1.0.0.7"; // 20140702
|
14 |
+
}
|
15 |
+
|
16 |
+
public function update($productXML)
|
17 |
+
{
|
18 |
+
$resultXMLData = new DOMDocument();
|
19 |
+
$productResultsXMLData = $resultXMLData->createElement('ProductResults');
|
20 |
+
$resultXMLData->appendChild($productResultsXMLData);
|
21 |
+
$productXMLData = simplexml_load_string($productXML);
|
22 |
+
|
23 |
+
$attributeHelper = Mage::helper('bulkapi/attribute');
|
24 |
+
$defaultAttributeSetId = $attributeHelper->getDefaultAttributeSetId();
|
25 |
+
$magentoAttributeList = Mage::getResourceModel('catalog/product_attribute_collection')->addVisibleFilter();
|
26 |
+
|
27 |
+
$attributeCache = Mage::helper('bulkapi/attributeCache');
|
28 |
+
$attributeCache->resetCache($magentoAttributeList);
|
29 |
+
|
30 |
+
foreach ($productXMLData as $productData)
|
31 |
+
{
|
32 |
+
$productResultXMLData = new DOMElement('ProductResult');
|
33 |
+
$productResultsXMLData->appendChild($productResultXMLData);
|
34 |
+
$this->updateOrCreateProduct($productData, $defaultAttributeSetId, $productResultXMLData, $attributeCache);
|
35 |
+
}
|
36 |
+
return $resultXMLData->saveXML();
|
37 |
+
}
|
38 |
+
|
39 |
+
private function updateOrCreateProduct($productData, $defaultAttributeSetId, $productResultXMLData, $attributeCache)
|
40 |
+
{
|
41 |
+
$productResultXMLData->appendChild(new DOMElement('StockNumber', $productData->StockNumber));
|
42 |
+
$productID = Mage::getModel('catalog/product')->getIdBySku($productData->StockNumber);
|
43 |
+
$addUpdateProduct = false;
|
44 |
+
|
45 |
+
// If the following SKUType is a SubSKU, we need to ignore the Variations node, as we do not want any attached listing SKU's.
|
46 |
+
if ((string)$productData->SKUType == "Sub")
|
47 |
+
{
|
48 |
+
$configurableDataSentFlag = 0;
|
49 |
+
}
|
50 |
+
else
|
51 |
+
{
|
52 |
+
$configurableDataSentFlag = (strcmp($productData->UseVariations,'Y') == 0);
|
53 |
+
}
|
54 |
+
|
55 |
+
if ($productID > 0)
|
56 |
+
{
|
57 |
+
// Product exists.
|
58 |
+
$addUpdateProduct = true;
|
59 |
+
$product = Mage::getModel('catalog/product')->load($productID);
|
60 |
+
}
|
61 |
+
else
|
62 |
+
{
|
63 |
+
// Product doesn't exist, but we only want to create it, if it is active.
|
64 |
+
if ((string)$productData->IsActive === 'Y')
|
65 |
+
{
|
66 |
+
$addUpdateProduct = true;
|
67 |
+
}
|
68 |
+
|
69 |
+
if ($addUpdateProduct)
|
70 |
+
{
|
71 |
+
$product = Mage::getModel('catalog/product');
|
72 |
+
$product->setSku($productData->StockNumber);
|
73 |
+
|
74 |
+
// Before setting the Product Type we need to know what the SKU type is, as only the "Master" can be configurable.
|
75 |
+
// SKUTypes = "Master", "Sub" or "Listing".
|
76 |
+
if ($configurableDataSentFlag && (string)$productData->SKUType == "Master")
|
77 |
+
{
|
78 |
+
$product->setTypeId(Mage_Catalog_Model_Product_Type::TYPE_CONFIGURABLE);
|
79 |
+
}
|
80 |
+
else
|
81 |
+
{
|
82 |
+
$product->setTypeId(Mage_Catalog_Model_Product_Type::TYPE_SIMPLE);
|
83 |
+
}
|
84 |
+
|
85 |
+
$product->setAttributeSetId($defaultAttributeSetId);
|
86 |
+
$product->setVisibility(Mage_Catalog_Model_Product_Visibility::VISIBILITY_BOTH);
|
87 |
+
}
|
88 |
+
}
|
89 |
+
|
90 |
+
if ($addUpdateProduct)
|
91 |
+
{
|
92 |
+
// Define the websites to use for the product
|
93 |
+
$productWebsites = Mage::helper('bulkapi/website');
|
94 |
+
$product->setWebsiteIds($productWebsites->getProductWebsiteIDs($productData));
|
95 |
+
|
96 |
+
// Assign any related products associated for the product
|
97 |
+
$productRelatedProducts = Mage::helper('bulkapi/relatedProducts');
|
98 |
+
$product->setRelatedLinkData($productRelatedProducts->getRelatedProducts($productData));
|
99 |
+
|
100 |
+
// Check to see if we have been asked to ignore categories
|
101 |
+
$this->setProductProperties($product,$productData);
|
102 |
+
if (strcmp($productData->IgnoreCategories,'Y') != 0)
|
103 |
+
{
|
104 |
+
$categoryHelper = Mage::helper('bulkapi/category');
|
105 |
+
$categoryHelper->setProductCategories($product,$productData);
|
106 |
+
}
|
107 |
+
|
108 |
+
// Check to see if we have been asked to ignore custom fields
|
109 |
+
if (strcmp($productData->IgnoreCustomFields,'Y') != 0)
|
110 |
+
{
|
111 |
+
$attributeHelper = Mage::helper('bulkapi/attribute');
|
112 |
+
$attributeHelper->setCustomFieldGroupValues($product,$productData, $attributeCache);
|
113 |
+
}
|
114 |
+
|
115 |
+
$imageHelper = Mage::helper('bulkapi/image');
|
116 |
+
$imageHelper->setImageList($product, $productData, $productResultXMLData); //$magentoAttributeList);
|
117 |
+
|
118 |
+
if ($configurableDataSentFlag)
|
119 |
+
{
|
120 |
+
$configurableHelper = Mage::helper('bulkapi/configurableProduct');
|
121 |
+
$configurableHelper->setConfigurableProducts($product, $productData, $attributeCache);
|
122 |
+
}
|
123 |
+
$product->save();
|
124 |
+
}
|
125 |
+
}
|
126 |
+
|
127 |
+
private function setProductProperties($magentoProduct, $productData)
|
128 |
+
{
|
129 |
+
$title = $this->getTitle($productData);
|
130 |
+
$magentoProduct->setName($title);
|
131 |
+
$magentoProduct->setMetaTitle($title);
|
132 |
+
|
133 |
+
// Make a double check we have the visibility of the product correct
|
134 |
+
if ((string)$productData->SKUType == "Sub")
|
135 |
+
{
|
136 |
+
$magentoProduct->setVisibility(Mage_Catalog_Model_Product_Visibility::VISIBILITY_NOT_VISIBLE);
|
137 |
+
}
|
138 |
+
else // SKUType is "Master" or "Listing" so should be visable
|
139 |
+
{
|
140 |
+
$magentoProduct->setVisibility(Mage_Catalog_Model_Product_Visibility::VISIBILITY_BOTH);
|
141 |
+
}
|
142 |
+
|
143 |
+
// Should we be ignoring any changes to the description
|
144 |
+
if (strcmp($productData->IgnoreDescription,'Y') != 0)
|
145 |
+
{
|
146 |
+
$magentoProduct->setDescription($productData->Description);
|
147 |
+
}
|
148 |
+
|
149 |
+
$magentoProduct->setShortDescription($productData->ShortDescription);
|
150 |
+
$magentoProduct->setPrice($productData->SellPrice);
|
151 |
+
|
152 |
+
// Include the CostPrice
|
153 |
+
$magentoProduct->setCost($productData->CostEach);
|
154 |
+
|
155 |
+
// Include the RRP price
|
156 |
+
$magentoProduct->setMsrp($productData->RRP);
|
157 |
+
|
158 |
+
// Include sales price info
|
159 |
+
if (((string)$productData->OnSale === 'Y') && ((string)$productData->SalePrice > '0'))
|
160 |
+
{
|
161 |
+
$magentoProduct->setSpecialPrice($productData->SalePrice);
|
162 |
+
$magentoProduct->setSpecialFromDate($productData->OnSaleStartDate);
|
163 |
+
$magentoProduct->setSpecialToDate($productData->OnSaleEndDate);
|
164 |
+
}
|
165 |
+
else
|
166 |
+
{
|
167 |
+
$magentoProduct->setSpecialPrice('');
|
168 |
+
$magentoProduct->setSpecialFromDate('');
|
169 |
+
$magentoProduct->setSpecialToDate('');
|
170 |
+
}
|
171 |
+
|
172 |
+
// Include Meta Data
|
173 |
+
$magentoProduct->setMetaKeyword($productData->Keywords);
|
174 |
+
$magentoProduct->setMetaDescription($productData->MetaDescription);
|
175 |
+
|
176 |
+
$active = ((string)$productData->IsActive === 'Y' ?
|
177 |
+
Mage_Catalog_Model_Product_Status::STATUS_ENABLED :
|
178 |
+
Mage_Catalog_Model_Product_Status::STATUS_DISABLED);
|
179 |
+
|
180 |
+
$magentoProduct->setStatus($active);
|
181 |
+
|
182 |
+
$magentoProduct->setWeight($productData->Weight);
|
183 |
+
$magentoProduct->setTaxClassId(2);
|
184 |
+
|
185 |
+
$stockData = array();
|
186 |
+
$stockData['qty'] = $productData->StockLevel;
|
187 |
+
//$this->_debug('stock level for product:'.$productData->StockLevel);
|
188 |
+
|
189 |
+
// Set the 'is_in_stock' to true incase this is a master,
|
190 |
+
// if it is a subsku and the StockLevel is 0, this will automatically get set to false anyhow.
|
191 |
+
$stockData['is_in_stock'] = 1;
|
192 |
+
$magentoProduct->setStockData($stockData);
|
193 |
+
}
|
194 |
+
|
195 |
+
private function getTitle($productData)
|
196 |
+
{
|
197 |
+
$title = $productData->WebsiteTitle;
|
198 |
+
if (strlen($title) == 0)
|
199 |
+
{
|
200 |
+
$title = $productData->ListingTitle;
|
201 |
+
}
|
202 |
+
if (strlen($title) == 0)
|
203 |
+
{
|
204 |
+
$title = $productData->Title;
|
205 |
+
}
|
206 |
+
return $title;
|
207 |
+
}
|
208 |
+
|
209 |
+
public function _debug($message)
|
210 |
+
{
|
211 |
+
Mage::log($message);
|
212 |
+
}
|
213 |
+
}
|
app/code/local/Sandbourne/BulkApi/Model/FullProduct/Api/V2.php
ADDED
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
class Sandbourne_BulkApi_Model_FullProduct_Api_V2 extends Sandbourne_BulkApi_Model_FullProduct_Api
|
3 |
+
{
|
4 |
+
public function update($productXML)
|
5 |
+
{
|
6 |
+
return parent::update($productXML);
|
7 |
+
}
|
8 |
+
|
9 |
+
public function version()
|
10 |
+
{
|
11 |
+
return parent::version();
|
12 |
+
}
|
13 |
+
}
|
14 |
+
|
app/code/local/Sandbourne/BulkApi/Model/PartialProduct/Api.php
ADDED
@@ -0,0 +1,57 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Sandbourne_BulkApi_Model_PartialProduct_Api extends Mage_Api_Model_Resource_Abstract
|
4 |
+
{
|
5 |
+
public function __construct()
|
6 |
+
{
|
7 |
+
//$this->_debug('PartialProduct constructed');
|
8 |
+
}
|
9 |
+
|
10 |
+
public function update($productXML)
|
11 |
+
{
|
12 |
+
$resultXMLData = new DOMDocument();
|
13 |
+
$productResultsXMLData = $resultXMLData->createElement('ProductResults');
|
14 |
+
$resultXMLData->appendChild($productResultsXMLData);
|
15 |
+
|
16 |
+
$productXMLData = simplexml_load_string($productXML);
|
17 |
+
|
18 |
+
foreach ($productXMLData as $productData)
|
19 |
+
{
|
20 |
+
//$this->_debug($productData->StockNumber);
|
21 |
+
$productResultXMLData = new DOMElement('ProductResult');
|
22 |
+
$productResultsXMLData->appendChild($productResultXMLData);
|
23 |
+
$this->updateProduct($productData, $productResultXMLData);
|
24 |
+
}
|
25 |
+
}
|
26 |
+
|
27 |
+
private function updateProduct($productData, $productResultXMLData)
|
28 |
+
{
|
29 |
+
$productID = Mage::getModel('catalog/product')->getIdBySku($productData->StockNumber);
|
30 |
+
if ($productID > 0)
|
31 |
+
{
|
32 |
+
//$this->_debug('product exists with id:'.$productID);
|
33 |
+
$product = Mage::getModel('catalog/product')->load($productID);
|
34 |
+
|
35 |
+
$active = ((string)$productData->IsActive === 'Y' ?
|
36 |
+
Mage_Catalog_Model_Product_Status::STATUS_ENABLED :
|
37 |
+
Mage_Catalog_Model_Product_Status::STATUS_DISABLED);
|
38 |
+
|
39 |
+
$product->setStatus($active);
|
40 |
+
$product->setPrice($productData->Price);
|
41 |
+
|
42 |
+
$stockData['qty'] = $productData->StockLevel;
|
43 |
+
//$this->_debug('stock level for product:'.$productData->StockLevel);
|
44 |
+
$inStock = ($productData->StockLevel > 0 ? 1 : 0);
|
45 |
+
$stockData['is_in_stock'] = $inStock;
|
46 |
+
|
47 |
+
$product->setStockData($stockData);
|
48 |
+
|
49 |
+
$product->save();
|
50 |
+
}
|
51 |
+
}
|
52 |
+
|
53 |
+
public function _debug($message)
|
54 |
+
{
|
55 |
+
Mage::log($message);
|
56 |
+
}
|
57 |
+
}
|
app/code/local/Sandbourne/BulkApi/Model/PartialProduct/Api/V2.php
ADDED
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Sandbourne_BulkApi_Model_PartialProduct_Api_V2 extends Sandbourne_BulkApi_Model_PartialProduct_Api
|
4 |
+
{
|
5 |
+
public function update($productXML)
|
6 |
+
{
|
7 |
+
return parent::update($productXML);
|
8 |
+
}
|
9 |
+
}
|
10 |
+
|
11 |
+
|
app/code/local/Sandbourne/BulkApi/Model/testatts.php
ADDED
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
echo "Line 2";
|
3 |
+
//$attributes = Mage::getResourceModel('catalog/product_attribute_collection')->addVisibleFilter();
|
4 |
+
$attributeArray = array();
|
5 |
+
echo "Line 5";
|
6 |
+
foreach($attributes as $attribute)
|
7 |
+
{
|
8 |
+
echo "Line 8";
|
9 |
+
$attributeArray[] = array(
|
10 |
+
'label' => $attribute->getData('frontend_label'),
|
11 |
+
'value' => $attribute->getData('attribute_code')
|
12 |
+
);
|
13 |
+
echo "Line 13";
|
14 |
+
}
|
15 |
+
// return $attributeArray;
|
16 |
+
?>
|
app/code/local/Sandbourne/BulkApi/etc/api.xml
ADDED
@@ -0,0 +1,79 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<config>
|
3 |
+
<api>
|
4 |
+
<resources>
|
5 |
+
<fullProduct translate="title" module="bulkapi">
|
6 |
+
<model>bulkapi/fullProduct_api</model>
|
7 |
+
<title>Product Bulk Processing Resource</title>
|
8 |
+
<acl>bulkapi_data</acl>
|
9 |
+
<methods>
|
10 |
+
<update translate="title" module="bulkapi">
|
11 |
+
<title>Bulk update product data</title>
|
12 |
+
<method>update</method>
|
13 |
+
</update>
|
14 |
+
<version translate="title" module="bulkapi">
|
15 |
+
<title>Version of the Bulk Api</title>
|
16 |
+
<method>version</method>
|
17 |
+
</version>
|
18 |
+
</methods>
|
19 |
+
<faults module="bulkapi">
|
20 |
+
<data_invalid>
|
21 |
+
<code>100</code>
|
22 |
+
<message>Invalid data. Details in error message.</message>
|
23 |
+
</data_invalid>
|
24 |
+
</faults>
|
25 |
+
</fullProduct>
|
26 |
+
<partialProduct translate="title" module="bulkapi">
|
27 |
+
<model>bulkapi/partialProduct_api</model>
|
28 |
+
<title>Partial Product Bulk Processing Resource</title>
|
29 |
+
<acl>bulkapi_data</acl>
|
30 |
+
<methods>
|
31 |
+
<update translate="title" module="bulkapi">
|
32 |
+
<title>Partial bulk update product data</title>
|
33 |
+
<method>update</method>
|
34 |
+
</update>
|
35 |
+
</methods>
|
36 |
+
<faults module="bulkapi">
|
37 |
+
<data_invalid>
|
38 |
+
<code>100</code>
|
39 |
+
<message>Invalid data. Details in error message.</message>
|
40 |
+
</data_invalid>
|
41 |
+
</faults>
|
42 |
+
</partialProduct>
|
43 |
+
<fullImage translate="title" module="bulkapi">
|
44 |
+
<model>bulkapi/fullImage_api</model>
|
45 |
+
<title>Full Image Bulk Processing Resource</title>
|
46 |
+
<acl>bulkapi_data</acl>
|
47 |
+
<methods>
|
48 |
+
<update translate="title" module="bulkapi">
|
49 |
+
<title>Full image update product data</title>
|
50 |
+
<method>update</method>
|
51 |
+
</update>
|
52 |
+
</methods>
|
53 |
+
<faults module="bulkapi">
|
54 |
+
<data_invalid>
|
55 |
+
<code>100</code>
|
56 |
+
<message>Invalid data. Details in error message.</message>
|
57 |
+
</data_invalid>
|
58 |
+
</faults>
|
59 |
+
</fullImage>
|
60 |
+
</resources>
|
61 |
+
<v2>
|
62 |
+
<resources_function_prefix>
|
63 |
+
<fullProduct>fullProduct</fullProduct>
|
64 |
+
<partialProduct>partialProduct</partialProduct>
|
65 |
+
<fullImage>fullImage</fullImage>
|
66 |
+
</resources_function_prefix>
|
67 |
+
</v2>
|
68 |
+
<acl>
|
69 |
+
<resources>
|
70 |
+
<bulkapi_data translate="title" module="bulkapi">
|
71 |
+
<title>Product Bulk Processing Resource</title>
|
72 |
+
<update translate="title" module="bulkapi">
|
73 |
+
<title>Update</title>
|
74 |
+
</update>
|
75 |
+
</bulkapi_data>
|
76 |
+
</resources>
|
77 |
+
</acl>
|
78 |
+
</api>
|
79 |
+
</config>
|
app/code/local/Sandbourne/BulkApi/etc/config.xml
ADDED
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<config>
|
3 |
+
<modules>
|
4 |
+
<Sandbourne_BulkApi>
|
5 |
+
<version>1.0.0.6</version>
|
6 |
+
</Sandbourne_BulkApi>
|
7 |
+
</modules>
|
8 |
+
<global>
|
9 |
+
<models>
|
10 |
+
<bulkapi>
|
11 |
+
<class>Sandbourne_BulkApi_Model</class>
|
12 |
+
</bulkapi>
|
13 |
+
</models>
|
14 |
+
<helpers>
|
15 |
+
<bulkapi>
|
16 |
+
<class>Sandbourne_BulkApi_Helper</class>
|
17 |
+
</bulkapi>
|
18 |
+
</helpers>
|
19 |
+
</global>
|
20 |
+
</config>
|
app/code/local/Sandbourne/BulkApi/etc/wsdl.xml
ADDED
@@ -0,0 +1,98 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0" encoding="UTF-8"?>
|
2 |
+
<definitions xmlns:typens="urn:{{var wsdl.name}}" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
|
3 |
+
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns="http://schemas.xmlsoap.org/wsdl/"
|
4 |
+
name="{{var wsdl.name}}" targetNamespace="urn:{{var wsdl.name}}">
|
5 |
+
<message name="fullProductUpdateRequest">
|
6 |
+
<part name="sessionId" type="xsd:string"/>
|
7 |
+
<part name="productXML" type="xsd:string"/>
|
8 |
+
</message>
|
9 |
+
<message name="fullProductVersionRequest">
|
10 |
+
<part name="sessionId" type="xsd:string"/>
|
11 |
+
</message>
|
12 |
+
<message name="partialProductUpdateRequest">
|
13 |
+
<part name="sessionId" type="xsd:string"/>
|
14 |
+
<part name="productXML" type="xsd:string"/>
|
15 |
+
</message>
|
16 |
+
<message name="fullImageUpdateRequest">
|
17 |
+
<part name="sessionId" type="xsd:string"/>
|
18 |
+
<part name="productXML" type="xsd:string"/>
|
19 |
+
</message>
|
20 |
+
<message name="fullProductUpdateResponse">
|
21 |
+
<part name="result" type="xsd:string" />
|
22 |
+
</message>
|
23 |
+
<message name="fullProductVersionResponse">
|
24 |
+
<part name="result" type="xsd:string" />
|
25 |
+
</message>
|
26 |
+
<message name="partialProductUpdateResponse">
|
27 |
+
<part name="result" type="xsd:string" />
|
28 |
+
</message>
|
29 |
+
<message name="fullImageUpdateResponse">
|
30 |
+
<part name="result" type="xsd:string" />
|
31 |
+
</message>
|
32 |
+
<portType name="{{var wsdl.handler}}PortType">
|
33 |
+
<operation name="fullProductUpdate">
|
34 |
+
<documentation>Creates or updates products in bulk</documentation>
|
35 |
+
<input message="typens:fullProductUpdateRequest" />
|
36 |
+
<output message="typens:fullProductUpdateResponse" />
|
37 |
+
</operation>
|
38 |
+
<operation name="fullProductVersion">
|
39 |
+
<documentation>Retrieves the version of the BulkAPI</documentation>
|
40 |
+
<input message="typens:fullProductVersionRequest" />
|
41 |
+
<output message="typens:fullProductVersionResponse" />
|
42 |
+
</operation>
|
43 |
+
<operation name="partialProductUpdate">
|
44 |
+
<documentation>Updates products using partial details in bulk</documentation>
|
45 |
+
<input message="typens:partialProductUpdateRequest" />
|
46 |
+
<output message="typens:partialProductUpdateResponse" />
|
47 |
+
</operation>
|
48 |
+
<operation name="fullImageUpdate">
|
49 |
+
<documentation>Updates product images using full details in bulk</documentation>
|
50 |
+
<input message="typens:fullImageUpdateRequest" />
|
51 |
+
<output message="typens:fullImageUpdateResponse" />
|
52 |
+
</operation>
|
53 |
+
</portType>
|
54 |
+
<binding name="{{var wsdl.handler}}Binding" type="typens:{{var wsdl.handler}}PortType">
|
55 |
+
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" />
|
56 |
+
<operation name="fullProductUpdate">
|
57 |
+
<soap:operation soapAction="urn:{{var wsdl.handler}}Action" />
|
58 |
+
<input>
|
59 |
+
<soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
|
60 |
+
</input>
|
61 |
+
<output>
|
62 |
+
<soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
|
63 |
+
</output>
|
64 |
+
</operation>
|
65 |
+
<operation name="fullProductVersion">
|
66 |
+
<soap:operation soapAction="urn:{{var wsdl.handler}}Action" />
|
67 |
+
<input>
|
68 |
+
<soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
|
69 |
+
</input>
|
70 |
+
<output>
|
71 |
+
<soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
|
72 |
+
</output>
|
73 |
+
</operation>
|
74 |
+
<operation name="partialProductUpdate">
|
75 |
+
<soap:operation soapAction="urn:{{var wsdl.handler}}Action" />
|
76 |
+
<input>
|
77 |
+
<soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
|
78 |
+
</input>
|
79 |
+
<output>
|
80 |
+
<soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
|
81 |
+
</output>
|
82 |
+
</operation>
|
83 |
+
<operation name="fullImageUpdate">
|
84 |
+
<soap:operation soapAction="urn:{{var wsdl.handler}}Action" />
|
85 |
+
<input>
|
86 |
+
<soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
|
87 |
+
</input>
|
88 |
+
<output>
|
89 |
+
<soap:body namespace="urn:{{var wsdl.name}}" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
|
90 |
+
</output>
|
91 |
+
</operation>
|
92 |
+
</binding>
|
93 |
+
<service name="{{var wsdl.name}}Service">
|
94 |
+
<port name="{{var wsdl.handler}}Port" binding="typens:{{var wsdl.handler}}Binding">
|
95 |
+
<soap:address location="{{var wsdl.url}}" />
|
96 |
+
</port>
|
97 |
+
</service>
|
98 |
+
</definitions>
|
app/etc/modules/Sandbourne_BulkApi.xml
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<config>
|
3 |
+
<modules>
|
4 |
+
<Sandbourne_BulkApi>
|
5 |
+
<active>true</active>
|
6 |
+
<codePool>local</codePool>
|
7 |
+
</Sandbourne_BulkApi>
|
8 |
+
</modules>
|
9 |
+
</config>
|
package.xml
CHANGED
@@ -1,18 +1,33 @@
|
|
1 |
<?xml version="1.0"?>
|
2 |
<package>
|
3 |
<name>eSellerProPlugin</name>
|
4 |
-
<version>1.0.0.
|
5 |
<stability>beta</stability>
|
6 |
<license uri="http://opensource.org/licenses/osl-3.0.php">OSL</license>
|
7 |
<channel>community</channel>
|
8 |
<extends/>
|
9 |
-
<summary>
|
10 |
-
<description
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
16 |
<compatible/>
|
17 |
<dependencies><required><php><min>5.1.0</min><max>6.0.0</max></php><package><name>Mage_Core_Modules</name><channel>Community</channel><min/><max/></package></required></dependencies>
|
18 |
</package>
|
1 |
<?xml version="1.0"?>
|
2 |
<package>
|
3 |
<name>eSellerProPlugin</name>
|
4 |
+
<version>1.0.0.7</version>
|
5 |
<stability>beta</stability>
|
6 |
<license uri="http://opensource.org/licenses/osl-3.0.php">OSL</license>
|
7 |
<channel>community</channel>
|
8 |
<extends/>
|
9 |
+
<summary>Extension to allow the creation, amendment and stock control of products from eSellerPro into Magento.</summary>
|
10 |
+
<description><p><i>You will need to be an existing <b>eSellerPro</b> customer to be able to use this extension. It will only work for those who are currently using eSellerPro. If you are an eSellerPro customer, then feel free to install this extension, but then you will need to contact your Account Manager for activatationt.</i></p>
|
11 |
+
<p>It allows the pushing of products from eSellerPro to Magento on a singular, or batch process, using eSellerPro's powerful Channel Profile. Below are some of the features supported:-</p>
|
12 |
+
<ul>
|
13 |
+
<li>Both Simple (Single) and Configurable (Variations) products.</li>
|
14 |
+
<li>Multiple Website.</li>
|
15 |
+
<li>Multiple Categories.</li>
|
16 |
+
<li>Customised Custom Field Groups.</li>
|
17 |
+
<li>Automatic Attribute creation.</li>
|
18 |
+
<li>Cost Price.</li>
|
19 |
+
<li>Manufacturer's Suggested Retail Price (RRP)</li>
|
20 |
+
<li>On Sale Price with Start and End dates.</li>
|
21 |
+
<li>Weight</li>
|
22 |
+
<li>Related Products</li>
|
23 |
+
<li>Multiple Images</li>
|
24 |
+
</ul>
|
25 |
+
<p>Orders are currently pulled from Magento into eSellerPro periodically. When an order is completed within eSellerPro, the Magento order status and any courier tracking numbers are updated.</p></description>
|
26 |
+
<notes>This is currently our beta, being tested by some customers. If you wish to join the beta programme, please contact your account manager at eSellelrPro.</notes>
|
27 |
+
<authors><author><name>eSellerPro</name><user>eSellerPro</user><email>magento@esellerpro.com</email></author></authors>
|
28 |
+
<date>2014-07-02</date>
|
29 |
+
<time>12:48:08</time>
|
30 |
+
<contents><target name="magelocal"><dir name="Sandbourne"><dir name="BulkApi"><dir name="Helper"><file name="Array.php" hash="0a04d7af6b6d84fed6d1a0097a558abf"/><file name="Attribute.php" hash="62ea78350400981a21ebd024c14a3327"/><file name="AttributeCache.php" hash="258e7fd95a78ff62ff121f4a4776a3a8"/><file name="AttributeOptionCache.php" hash="be30b904d71df0f46f62ed77d6e2fc93"/><file name="Category.php" hash="58c7ca193933025e03cda2ebbcf75b27"/><file name="CategoryCache.php" hash="9201e35bd5e461e5483ea9b66b1306d0"/><file name="ConfigurableProduct.php" hash="6127acd0c0d96a864ed6294ef5445ebd"/><file name="Data.php" hash="7aa739540136122fdba1fa12c72a9cad"/><file name="Image.php" hash="1753b2b15ed4e7c4930c1603c44711e2"/><file name="RelatedProducts.php" hash="e927612b277080a5c835d0ceebd8598c"/><file name="TestData.php" hash="aa72f88ab2ee8cf218e43f59a846da56"/><file name="Utils.php" hash="29beb209f25ab4a462051be7fa6c681b"/><file name="Website.php" hash="0e67b9ba7cd1bbfe8c840991d0aa3079"/></dir><dir name="Model"><dir name="FullImage"><dir name="Api"><file name="V2.php" hash="d998bacd61159399567d1c46e63507a2"/></dir><file name="Api.php" hash="fcff5388032e5cde7485314c6a1d3bf2"/></dir><dir name="FullProduct"><dir name="Api"><file name="V2.php" hash="3cfb906b7c4c72906e3baccb4fdeee40"/></dir><file name="Api.php" hash="943f4aa166fc557f161620d143b0a412"/></dir><dir name="PartialProduct"><dir name="Api"><file name="V2.php" hash="5e9375e74f6ba74bb79f20cce7574ba7"/></dir><file name="Api.php" hash="4175a73c303f07ffed2df5fb1295844e"/></dir><file name="testatts.php" hash="c519db8a12356abfc81a84148809291a"/></dir><dir name="etc"><file name="api.xml" hash="ee96f5255bb710f934c2dcef8e35cd89"/><file name="config.xml" hash="28ba1d03ffbc9c8a641674133a7207f6"/><file name="wsdl.xml" hash="9e291f850362a99b265645a978e45b09"/></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="Sandbourne_BulkApi.xml" hash="4418f8514205d4d52a309e83d5050c0d"/></dir></target></contents>
|
31 |
<compatible/>
|
32 |
<dependencies><required><php><min>5.1.0</min><max>6.0.0</max></php><package><name>Mage_Core_Modules</name><channel>Community</channel><min/><max/></package></required></dependencies>
|
33 |
</package>
|