eSellerProPlugin - Version 1.0.0.7

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

Files changed (25) hide show
  1. app/code/local/Sandbourne/BulkApi/Helper/Array.php +36 -0
  2. app/code/local/Sandbourne/BulkApi/Helper/Attribute.php +227 -0
  3. app/code/local/Sandbourne/BulkApi/Helper/AttributeCache.php +97 -0
  4. app/code/local/Sandbourne/BulkApi/Helper/AttributeOptionCache.php +40 -0
  5. app/code/local/Sandbourne/BulkApi/Helper/Category.php +76 -0
  6. app/code/local/Sandbourne/BulkApi/Helper/CategoryCache.php +55 -0
  7. app/code/local/Sandbourne/BulkApi/Helper/ConfigurableProduct.php +218 -0
  8. app/code/local/Sandbourne/BulkApi/Helper/Data.php +17 -0
  9. app/code/local/Sandbourne/BulkApi/Helper/Image.php +119 -0
  10. app/code/local/Sandbourne/BulkApi/Helper/RelatedProducts.php +43 -0
  11. app/code/local/Sandbourne/BulkApi/Helper/TestData.php +561 -0
  12. app/code/local/Sandbourne/BulkApi/Helper/Utils.php +70 -0
  13. app/code/local/Sandbourne/BulkApi/Helper/Website.php +120 -0
  14. app/code/local/Sandbourne/BulkApi/Model/FullImage/Api.php +91 -0
  15. app/code/local/Sandbourne/BulkApi/Model/FullImage/Api/V2.php +9 -0
  16. app/code/local/Sandbourne/BulkApi/Model/FullProduct/Api.php +213 -0
  17. app/code/local/Sandbourne/BulkApi/Model/FullProduct/Api/V2.php +14 -0
  18. app/code/local/Sandbourne/BulkApi/Model/PartialProduct/Api.php +57 -0
  19. app/code/local/Sandbourne/BulkApi/Model/PartialProduct/Api/V2.php +11 -0
  20. app/code/local/Sandbourne/BulkApi/Model/testatts.php +16 -0
  21. app/code/local/Sandbourne/BulkApi/etc/api.xml +79 -0
  22. app/code/local/Sandbourne/BulkApi/etc/config.xml +20 -0
  23. app/code/local/Sandbourne/BulkApi/etc/wsdl.xml +98 -0
  24. app/etc/modules/Sandbourne_BulkApi.xml +9 -0
  25. 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.6</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>Summary in here</summary>
10
- <description>Description in here</description>
11
- <notes>DO NOT USE</notes>
12
- <authors><author><name>eSellerPro</name><user>eSellerPro</user><email>info@esellerpro.com</email></author></authors>
13
- <date>2014-06-23</date>
14
- <time>14:32:38</time>
15
- <contents><target name="magelocal"><dir name="."><dir name="app"><dir name="etc"><file name="modules" hash=""/></dir></dir></dir></target></contents>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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>&lt;p&gt;&lt;i&gt;You will need to be an existing &lt;b&gt;eSellerPro&lt;/b&gt; 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.&lt;/i&gt;&lt;/p&gt;&#xD;
11
+ &lt;p&gt;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:-&lt;/p&gt;&#xD;
12
+ &lt;ul&gt;&#xD;
13
+ &lt;li&gt;Both Simple (Single) and Configurable (Variations) products.&lt;/li&gt;&#xD;
14
+ &lt;li&gt;Multiple Website.&lt;/li&gt;&#xD;
15
+ &lt;li&gt;Multiple Categories.&lt;/li&gt;&#xD;
16
+ &lt;li&gt;Customised Custom Field Groups.&lt;/li&gt;&#xD;
17
+ &lt;li&gt;Automatic Attribute creation.&lt;/li&gt;&#xD;
18
+ &lt;li&gt;Cost Price.&lt;/li&gt;&#xD;
19
+ &lt;li&gt;Manufacturer's Suggested Retail Price (RRP)&lt;/li&gt;&#xD;
20
+ &lt;li&gt;On Sale Price with Start and End dates.&lt;/li&gt;&#xD;
21
+ &lt;li&gt;Weight&lt;/li&gt;&#xD;
22
+ &lt;li&gt;Related Products&lt;/li&gt;&#xD;
23
+ &lt;li&gt;Multiple Images&lt;/li&gt;&#xD;
24
+ &lt;/ul&gt;&#xD;
25
+ &lt;p&gt;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.&lt;/p&gt;</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>