Camiloo_Channelunity - Version 1.0.0.9

Version Notes

The ChannelUnity connector kit for Magento.
Fixes a problem with VAT/Tax on orders imported. Supports ignoring of Disabled products in Magento. Fixes image on product save event. Fixes stock sync from Magento to CU on order placed and invoice paid events.

Download this release

Release Info

Developer Magento Core Team
Extension Camiloo_Channelunity
Version 1.0.0.9
Comparing to
See all releases


Code changes from version 1.0.0.8 to 1.0.0.9

app/code/community/Camiloo/Channelunity/Model/Abstract.php CHANGED
@@ -288,5 +288,53 @@ class Camiloo_Channelunity_Model_Abstract
288
 
289
  return $result;
290
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
291
  }
292
  ?>
288
 
289
  return $result;
290
  }
291
+
292
+
293
+ /**
294
+ * skipProduct - checks whether to skip product to pass it to CU
295
+ *
296
+ * @param type $product - can be product id or product object
297
+ *
298
+ * @return boolean - true-skip, false-don't skip
299
+ */
300
+ public function skipProduct($product)
301
+ {
302
+ $productStatus = 1;
303
+
304
+ $ignoreDisabled = Mage::getStoreConfig('channelunityint/generalsettings/ignoredisabledproducts');
305
+
306
+ if($product && $ignoreDisabled == 1)
307
+ {
308
+ if(is_int($product)) {
309
+ $product = Mage::getModel('catalog/product')->load($product);
310
+ }
311
+
312
+ if(is_object($product) && $product->hasSku()) {
313
+ $productStatus = $product->getStatus(); // 1-Enabled, 2-Disabled
314
+ }
315
+
316
+ if($productStatus == 2) {
317
+ return true;
318
+ }
319
+ }
320
+
321
+ return false;
322
+ }
323
+
324
+ /**
325
+ * skipProduct - checks whether to skip product to pass it to CU
326
+ *
327
+ * //product field: status, 1-Enabled, 2-Disabled
328
+ *
329
+ * @return boolean - true-ignore disabled, false-don't ignore
330
+ */
331
+ public function ignoreDisabled()
332
+ {
333
+ $ignoreDisabled = false;
334
+
335
+ $ignoreDisabled = Mage::getStoreConfig('channelunityint/generalsettings/ignoredisabledproducts');
336
+
337
+ return $ignoreDisabled;
338
+ }
339
  }
340
  ?>
app/code/community/Camiloo/Channelunity/Model/Observer.php CHANGED
@@ -1,295 +1,395 @@
1
  <?php
 
2
  /**
3
- * ChannelUnity connector for Magento Commerce
4
  *
5
  * @category Camiloo
6
  * @package Camiloo_Channelunity
7
  * @copyright Copyright (c) 2012 Camiloo Limited (http://www.camiloo.co.uk)
8
  * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
9
  */
 
10
  /**
11
  * ChannelUnity observers.
12
  * Posts events to the CU cloud when various Magento events occur.
13
  */
14
- class Camiloo_Channelunity_Model_Observer extends Camiloo_Channelunity_Model_Abstract {
15
-
 
16
  /**
17
  * Called on saving a product in Magento.
18
  */
19
- public function productWasSaved(Varien_Event_Observer $observer) {
 
20
  try {
21
  $product = $observer->getEvent()->getProduct();
22
-
23
- $storeViewId = $product->getStoreId();
24
 
25
- $xml = "<Products>\n";
26
- $xml .= "<SourceURL>".Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_WEB)
27
- ."</SourceURL>\n";
28
-
29
- $xml .= "<StoreViewId>$storeViewId</StoreViewId>\n";
30
-
31
- $xml .= Mage::getModel('channelunity/products')->generateCuXmlForSingleProduct($product->getId(), $storeViewId);
32
-
33
- $xml .= "</Products>\n";
34
-
35
- $this->postToChannelUnity($xml, "ProductData");
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36
  }
37
  catch (Exception $x) {
 
38
  }
39
  }
40
-
41
  /**
42
  * Called on deleting a product in Magento.
43
  */
44
- public function productWasDeleted(Varien_Event_Observer $observer) {
45
- try {
 
46
  $product = $observer->getEvent()->getProduct();
47
-
48
  $storeViewId = $product->getStoreId();
49
-
50
  $xml = "<Products>\n";
51
- $xml .= "<SourceURL>".Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_WEB)
52
- ."</SourceURL>\n";
 
53
  $xml .= "<StoreViewId>$storeViewId</StoreViewId>\n";
54
- $xml .= "<ProductID>{$product->getId()}</ProductID>\n";
55
- $xml .= "<Deleted>TRUE</Deleted>\n";
56
-
57
  $xml .= "</Products>\n";
58
-
59
  $this->postToChannelUnity($xml, "ProductData");
60
-
61
- }
62
- catch (Exception $x) {
63
  }
64
  }
65
-
66
  /**
67
  * Allows the observing of more generic events in Magento.
68
  * Useful in multiple product save for example.
69
  */
70
- public function hookToControllerActionPostDispatch($observer) {
 
71
  try {
72
  $evname = $observer->getEvent()->getControllerAction()->getFullActionName();
73
-
74
- if ($evname == 'adminhtml_catalog_product_action_attribute_save')
75
- {
76
  $xml = "<Products>\n";
77
- $xml .= "<SourceURL>".Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_WEB)
78
- ."</SourceURL>\n";
79
-
80
  $storeViewId = Mage::helper('adminhtml/catalog_product_edit_action_attribute')->getSelectedStoreId();
81
  $xml .= "<StoreViewId>$storeViewId</StoreViewId>\n";
82
-
83
  $pids = Mage::helper('adminhtml/catalog_product_edit_action_attribute')->getProductIds();
84
-
85
  foreach ($pids as $productId) {
86
  $xml .= Mage::getModel('channelunity/products')->generateCuXmlForSingleProduct(
87
- $productId, $storeViewId);
88
  }
89
-
90
  $xml .= "</Products>\n";
91
-
92
  $this->postToChannelUnity($xml, "ProductData");
93
- }
94
- else if ($evname == 'adminhtml_catalog_category_save') {
95
-
96
  $this->categorySave($observer);
97
- }
98
- else if ($evname == 'adminhtml_catalog_category_delete') {
99
-
100
  $this->categoryDelete($observer);
101
- }
102
- else if ($evname == 'adminhtml_catalog_product_delete') {
103
  $xml = "<Products>\n";
104
- $xml .= "<SourceURL>".Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_WEB)
105
- ."</SourceURL>\n";
106
-
107
  $storeViewId = Mage::helper('adminhtml/catalog_product_edit_action_attribute')->getSelectedStoreId();
108
  $xml .= "<StoreViewId>$storeViewId</StoreViewId>\n";
109
-
110
  $productId = $observer->getEvent()->getControllerAction()->getRequest()->getParam('id');
111
-
112
- $xml .= "<DeletedProductId>".$productId."</DeletedProductId>\n";
113
-
114
  $xml .= "</Products>\n";
115
-
116
  $this->postToChannelUnity($xml, "ProductData");
117
- }
118
- }
119
- catch (Exception $x) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
120
  }
121
  }
122
-
123
  /**
124
  * Called on placing an order. Stock levels are updated on CU.
125
  */
126
  public function orderWasPlaced(Varien_Event_Observer $observer)
127
- {
128
  try {
129
  if (is_object($observer)) {
130
-
131
  $ev = $observer->getEvent();
132
-
133
  if (is_object($ev)) {
134
-
135
  $order = $ev->getOrder();
136
-
137
  if (is_object($order)) {
138
-
139
  $items = $order->getAllItems();
140
-
141
  $this->getItemsForUpdateCommon($items, $order->getStore()->getId());
142
-
143
  }
144
  }
145
  }
 
 
146
  }
147
- catch (Exception $x) {
148
- }
149
- }
150
-
151
- public function getItemsForUpdateCommon($items, $storeId) {
152
  try {
 
 
 
 
 
 
153
  foreach ($items as $item) {
154
-
155
  $sku = $item->getSku();
156
-
157
  $prodTemp = Mage::getModel('catalog/product')->loadByAttribute('sku', $sku);
158
  if (!$prodTemp) {
159
-
160
  continue;
161
  }
162
 
163
  // Item was ordered on website, stock will have reduced, update to CU
164
- $xml = Mage::getModel('channelunity/products')->generateCuXmlForSingleProduct(
165
- $prodTemp->getId(), $storeId, $item->getQtyOrdered());
166
-
167
- $this->postToChannelUnity($xml, "ProductData");
168
  }
 
 
 
 
 
 
169
  }
170
- catch (Exception $x) {
171
- }
172
- }
173
-
174
  public function onInvoicePaid(Varien_Event_Observer $observer)
175
- {
176
  try {
177
- if (is_object($observer) && is_object($observer->getInvoice()))
178
- {
179
  $order = $observer->getInvoice()->getOrder();
180
-
181
- if (is_object($order))
182
- {
183
  $items = $order->getAllItems();
184
  $this->getItemsForUpdateCommon($items, $order->getStore()->getId());
185
  }
186
  }
 
 
187
  }
188
- catch (Exception $x) {
189
- }
190
- }
191
-
192
  /**
193
  * Order is cancelled and has been saved. post order status change msg to CU
194
  */
195
- public function checkForCancellation(Varien_Event_Observer $observer) {
 
196
  try {
197
  $order = $observer->getOrder();
198
-
199
  $xml = Mage::getModel('channelunity/orders')->generateCuXmlForOrderStatus($order);
200
  $this->postToChannelUnity($xml, "OrderStatusUpdate");
 
 
201
  }
202
- catch (Exception $x) {
203
- }
204
- }
205
 
206
  /**
207
  * Send shipment to CU when tracking information is added.
208
  */
209
  public function saveTrackingToAmazon(Varien_Event_Observer $observer)
210
- {
211
  try {
212
  // Only mark as shipped when order has tracking information.
213
  $track = $observer->getEvent()->getTrack();
214
  $order = $track->getShipment()->getOrder();
215
-
216
  if ($track->getCarrierCode() == "custom") {
217
- $carrierName = $track->getTitle();
218
  } else {
219
  $carrierName = $track->getCarrierCode();
220
  }
221
-
222
- $xml = Mage::getModel('channelunity/orders')->generateCuXmlForOrderShip($order,
223
- $carrierName,
224
- $track->getTitle(),
225
- $track->getNumber());
226
- $this->postToChannelUnity($xml, "OrderStatusUpdate");
227
- }
228
- catch (Exception $x) {
229
  }
230
- }
231
 
232
  public function shipAmazon(Varien_Event_Observer $observer)
233
  {
234
  try {
235
  $shipment = $observer->getEvent()->getShipment();
236
  $order = $shipment->getOrder();
237
-
238
- $xml = Mage::getModel('channelunity/orders')->generateCuXmlForOrderShip($order,
239
- "",
240
- "",
241
- "");
242
- $this->postToChannelUnity($xml, "OrderStatusUpdate");
243
- }
244
- catch (Exception $x) {
245
  }
246
  }
247
-
248
  /**
249
  * Category is saved. CU needs to know about it.
250
  */
251
- public function categorySave(Varien_Event_Observer $observer) {
 
252
  try {
253
  $myStoreURL = Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_WEB);
254
  $categoryStatus = Mage::getModel('channelunity/categories')->postCategoriesToCU($myStoreURL);
255
- }
256
- catch (Exception $x) {
 
 
257
  }
258
  }
259
-
260
- public function configSaveAfter(Varien_Event_Observer $observer) {
 
261
  try {
262
  if (is_object($observer)) {
263
  $event = $observer->getEvent();
264
-
265
  if (is_object($event)) {
266
-
267
  $configData = $event->getData('config_data');
268
-
269
  if (is_object($configData)) {
270
-
271
  $configData = $configData->getData();
272
-
273
  if (isset($configData['fieldset_data'])) {
274
-
275
  $fieldset_data = $configData['fieldset_data'];
276
-
277
-
278
  if (isset($fieldset_data['merchantname'])) {
279
-
280
  $merchantName = $fieldset_data['merchantname'];
281
-
282
  Mage::getModel('channelunity/products')->postMyURLToChannelUnity($merchantName);
283
-
284
  }
285
-
286
  }
287
  }
288
  }
289
  }
 
 
 
 
290
  }
291
- catch (Exception $x) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
292
  }
293
  }
 
294
  }
295
- ?>
1
  <?php
2
+
3
  /**
4
+ * ChannelUnity connector for Magento Commerce
5
  *
6
  * @category Camiloo
7
  * @package Camiloo_Channelunity
8
  * @copyright Copyright (c) 2012 Camiloo Limited (http://www.camiloo.co.uk)
9
  * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
10
  */
11
+
12
  /**
13
  * ChannelUnity observers.
14
  * Posts events to the CU cloud when various Magento events occur.
15
  */
16
+ class Camiloo_Channelunity_Model_Observer extends Camiloo_Channelunity_Model_Abstract
17
+ {
18
+
19
  /**
20
  * Called on saving a product in Magento.
21
  */
22
+ public function productWasSaved(Varien_Event_Observer $observer)
23
+ {
24
  try {
25
  $product = $observer->getEvent()->getProduct();
 
 
26
 
27
+ $skipProduct = Mage::getModel('channelunity/products')->skipProduct($product);
28
+
29
+ $storeViewId = $product->getStoreId();
30
+
31
+ if(!$skipProduct)
32
+ {
33
+ $xml = "<Products>\n";
34
+
35
+ $xml .= "<SourceURL>".Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_WEB)."</SourceURL>\n";
36
+
37
+ $xml .= "<StoreViewId>$storeViewId</StoreViewId>\n";
38
+
39
+ $xml .= Mage::getModel('channelunity/products')->generateCuXmlForSingleProduct($product->getId(), $storeViewId);
40
+
41
+ $xml .= "</Products>\n";
42
+
43
+ $this->postToChannelUnity($xml, "ProductData");
44
+ } else {
45
+ $xml = "<Products>\n";
46
+
47
+ $xml .= "<SourceURL>" . Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_WEB)."</SourceURL>\n";
48
+
49
+ $xml .= "<StoreViewId>$storeViewId</StoreViewId>\n";
50
+
51
+ $xml .= "<DeletedProductId>{$product->getId()}</DeletedProductId>\n";
52
+
53
+ $xml .= "</Products>\n";
54
+
55
+ $this->postToChannelUnity($xml, "ProductData");
56
+ }
57
  }
58
  catch (Exception $x) {
59
+ Mage::logException($e);
60
  }
61
  }
62
+
63
  /**
64
  * Called on deleting a product in Magento.
65
  */
66
+ public function productWasDeleted(Varien_Event_Observer $observer)
67
+ {
68
+ try {
69
  $product = $observer->getEvent()->getProduct();
70
+
71
  $storeViewId = $product->getStoreId();
72
+
73
  $xml = "<Products>\n";
74
+
75
+ $xml .= "<SourceURL>" . Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_WEB)
76
+ . "</SourceURL>\n";
77
  $xml .= "<StoreViewId>$storeViewId</StoreViewId>\n";
78
+
79
+ $xml .= "<DeletedProductId>{$product->getId()}</DeletedProductId>\n";
80
+
81
  $xml .= "</Products>\n";
82
+
83
  $this->postToChannelUnity($xml, "ProductData");
84
+ } catch (Exception $e) {
85
+ Mage::logException($e);
 
86
  }
87
  }
88
+
89
  /**
90
  * Allows the observing of more generic events in Magento.
91
  * Useful in multiple product save for example.
92
  */
93
+ public function hookToControllerActionPostDispatch($observer)
94
+ {
95
  try {
96
  $evname = $observer->getEvent()->getControllerAction()->getFullActionName();
97
+
98
+ if ($evname == 'adminhtml_catalog_product_action_attribute_save') {
 
99
  $xml = "<Products>\n";
100
+ $xml .= "<SourceURL>" . Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_WEB)
101
+ . "</SourceURL>\n";
102
+
103
  $storeViewId = Mage::helper('adminhtml/catalog_product_edit_action_attribute')->getSelectedStoreId();
104
  $xml .= "<StoreViewId>$storeViewId</StoreViewId>\n";
105
+
106
  $pids = Mage::helper('adminhtml/catalog_product_edit_action_attribute')->getProductIds();
107
+
108
  foreach ($pids as $productId) {
109
  $xml .= Mage::getModel('channelunity/products')->generateCuXmlForSingleProduct(
110
+ $productId, $storeViewId);
111
  }
112
+
113
  $xml .= "</Products>\n";
114
+
115
  $this->postToChannelUnity($xml, "ProductData");
116
+ } else if ($evname == 'adminhtml_catalog_category_save') {
117
+
 
118
  $this->categorySave($observer);
119
+ } else if ($evname == 'adminhtml_catalog_category_delete') {
120
+
 
121
  $this->categoryDelete($observer);
122
+ } else if ($evname == 'adminhtml_catalog_product_delete') {
 
123
  $xml = "<Products>\n";
124
+ $xml .= "<SourceURL>" . Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_WEB)
125
+ . "</SourceURL>\n";
126
+
127
  $storeViewId = Mage::helper('adminhtml/catalog_product_edit_action_attribute')->getSelectedStoreId();
128
  $xml .= "<StoreViewId>$storeViewId</StoreViewId>\n";
129
+
130
  $productId = $observer->getEvent()->getControllerAction()->getRequest()->getParam('id');
131
+
132
+ $xml .= "<DeletedProductId>" . $productId . "</DeletedProductId>\n";
133
+
134
  $xml .= "</Products>\n";
135
+
136
  $this->postToChannelUnity($xml, "ProductData");
137
+ } else if ($evname == 'adminhtml_catalog_product_massStatus') { //update all products status on the massive status update
138
+
139
+ $updatedProductsId = $observer->getEvent()->getControllerAction()->getRequest()->getParam('product');
140
+ $status = $observer->getEvent()->getControllerAction()->getRequest()->getParam('status');
141
+
142
+ if(is_array($updatedProductsId) && !empty($updatedProductsId))
143
+ {
144
+ $storeViewId = Mage::helper('adminhtml/catalog_product_edit_action_attribute')->getSelectedStoreId();
145
+
146
+ $xml = "<Products>\n";
147
+ $xml .= "<SourceURL>" . Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_WEB)."</SourceURL>\n";
148
+ $xml .= "<StoreViewId>{$storeViewId}</StoreViewId>\n";
149
+
150
+ foreach ($updatedProductsId as $productId)
151
+ {
152
+ $product = Mage::getModel('catalog/product')->load($productId);
153
+
154
+ $skipProduct = Mage::getModel('channelunity/products')->skipProduct($product);
155
+
156
+ if($skipProduct)
157
+ {
158
+ $xml .= "<DeletedProductId>" . $productId . "</DeletedProductId>\n";
159
+ } else {
160
+ $xml .= Mage::getModel('channelunity/products')->generateCuXmlForSingleProduct($productId, $storeViewId);
161
+ }
162
+ }
163
+
164
+ $xml .= "</Products>\n";
165
+
166
+ $this->postToChannelUnity($xml, "ProductData");
167
+ }
168
+
169
+ }
170
+ } catch (Exception $e) {
171
+ Mage::logException($e);
172
  }
173
  }
174
+
175
  /**
176
  * Called on placing an order. Stock levels are updated on CU.
177
  */
178
  public function orderWasPlaced(Varien_Event_Observer $observer)
179
+ {
180
  try {
181
  if (is_object($observer)) {
182
+
183
  $ev = $observer->getEvent();
184
+
185
  if (is_object($ev)) {
186
+
187
  $order = $ev->getOrder();
188
+
189
  if (is_object($order)) {
190
+
191
  $items = $order->getAllItems();
192
+
193
  $this->getItemsForUpdateCommon($items, $order->getStore()->getId());
 
194
  }
195
  }
196
  }
197
+ } catch (Exception $e) {
198
+ Mage::logException($e);
199
  }
200
+ }
201
+
202
+ public function getItemsForUpdateCommon($items, $storeId)
203
+ {
 
204
  try {
205
+ $xml = "<Products>\n";
206
+ $xml .= "<SourceURL>" . Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_WEB)
207
+ . "</SourceURL>\n";
208
+
209
+ $xml .= "<StoreViewId>$storeId</StoreViewId>\n";
210
+
211
  foreach ($items as $item) {
212
+
213
  $sku = $item->getSku();
214
+
215
  $prodTemp = Mage::getModel('catalog/product')->loadByAttribute('sku', $sku);
216
  if (!$prodTemp) {
217
+
218
  continue;
219
  }
220
 
221
  // Item was ordered on website, stock will have reduced, update to CU
222
+ $xml .= Mage::getModel('channelunity/products')->generateCuXmlForSingleProduct(
223
+ $prodTemp->getId(), $storeId, 0 /* $item->getQtyOrdered() */);
224
+
 
225
  }
226
+ $xml .= "</Products>\n";
227
+
228
+ $this->postToChannelUnity($xml, "ProductData");
229
+
230
+ } catch (Exception $x) {
231
+ Mage::logException($e);
232
  }
233
+ }
234
+
 
 
235
  public function onInvoicePaid(Varien_Event_Observer $observer)
236
+ {
237
  try {
238
+ if (is_object($observer) && is_object($observer->getInvoice())) {
 
239
  $order = $observer->getInvoice()->getOrder();
240
+
241
+ if (is_object($order)) {
 
242
  $items = $order->getAllItems();
243
  $this->getItemsForUpdateCommon($items, $order->getStore()->getId());
244
  }
245
  }
246
+ } catch (Exception $e) {
247
+ Mage::logException($e);
248
  }
249
+ }
250
+
 
 
251
  /**
252
  * Order is cancelled and has been saved. post order status change msg to CU
253
  */
254
+ public function checkForCancellation(Varien_Event_Observer $observer)
255
+ {
256
  try {
257
  $order = $observer->getOrder();
258
+
259
  $xml = Mage::getModel('channelunity/orders')->generateCuXmlForOrderStatus($order);
260
  $this->postToChannelUnity($xml, "OrderStatusUpdate");
261
+ } catch (Exception $e) {
262
+ Mage::logException($e);
263
  }
264
+ }
 
 
265
 
266
  /**
267
  * Send shipment to CU when tracking information is added.
268
  */
269
  public function saveTrackingToAmazon(Varien_Event_Observer $observer)
270
+ {
271
  try {
272
  // Only mark as shipped when order has tracking information.
273
  $track = $observer->getEvent()->getTrack();
274
  $order = $track->getShipment()->getOrder();
275
+
276
  if ($track->getCarrierCode() == "custom") {
277
+ $carrierName = $track->getTitle();
278
  } else {
279
  $carrierName = $track->getCarrierCode();
280
  }
281
+
282
+ $xml = Mage::getModel('channelunity/orders')->generateCuXmlForOrderShip($order, $carrierName, $track->getTitle(), $track->getNumber());
283
+ $result = $this->postToChannelUnity($xml, "OrderStatusUpdate");
284
+ Mage::log('saveTrackingToAmazon: ' . $result);
285
+ } catch (Exception $e) {
286
+ Mage::logException($e);
 
 
287
  }
288
+ }
289
 
290
  public function shipAmazon(Varien_Event_Observer $observer)
291
  {
292
  try {
293
  $shipment = $observer->getEvent()->getShipment();
294
  $order = $shipment->getOrder();
295
+
296
+ $xml = Mage::getModel('channelunity/orders')->generateCuXmlForOrderShip($order, "", "", "");
297
+ $result = $this->postToChannelUnity($xml, "OrderStatusUpdate");
298
+ Mage::log('shipAmazon: ' . $result);
299
+ } catch (Exception $e) {
300
+
301
+ Mage::logException($e);
 
302
  }
303
  }
304
+
305
  /**
306
  * Category is saved. CU needs to know about it.
307
  */
308
+ public function categorySave(Varien_Event_Observer $observer)
309
+ {
310
  try {
311
  $myStoreURL = Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_WEB);
312
  $categoryStatus = Mage::getModel('channelunity/categories')->postCategoriesToCU($myStoreURL);
313
+ } catch (Exception $e) {
314
+
315
+ Mage::logException($e);
316
+
317
  }
318
  }
319
+
320
+ public function configSaveAfter(Varien_Event_Observer $observer)
321
+ {
322
  try {
323
  if (is_object($observer)) {
324
  $event = $observer->getEvent();
325
+
326
  if (is_object($event)) {
327
+
328
  $configData = $event->getData('config_data');
329
+
330
  if (is_object($configData)) {
331
+
332
  $configData = $configData->getData();
333
+
334
  if (isset($configData['fieldset_data'])) {
335
+
336
  $fieldset_data = $configData['fieldset_data'];
337
+
338
+
339
  if (isset($fieldset_data['merchantname'])) {
340
+
341
  $merchantName = $fieldset_data['merchantname'];
342
+
343
  Mage::getModel('channelunity/products')->postMyURLToChannelUnity($merchantName);
 
344
  }
 
345
  }
346
  }
347
  }
348
  }
349
+ } catch (Exception $e) {
350
+
351
+ Mage::logException($e);
352
+
353
  }
354
+ }
355
+
356
+ /**
357
+ * Triggers on a store delete event. Removes store and category data in CU.
358
+ * @author Matthew Gribben
359
+ *
360
+ * @param Varien_Event_Observer $observer
361
+ */
362
+ public function storeDelete(Varien_Event_Observer $observer)
363
+ {
364
+
365
+ $event = $observer->getEvent();
366
+ $store = $event->getStore();
367
+
368
+ try {
369
+
370
+
371
+ $xml = "<StoreDelete>\n";
372
+ $xml .= "<SourceURL>" . Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_WEB)
373
+ . "</SourceURL>\n";
374
+
375
+ $storeViewId = $store->getId();
376
+ $storeId = $store->getGroupId();
377
+ $websiteId = $store->getWebsiteId();
378
+
379
+ $xml .= "<StoreId>" . $storeId . "</StoreId>\n";
380
+ $xml .= "<DeletedStoreViewId>" . $storeViewId . "</DeletedStoreViewId>\n";
381
+ $xml .= "<WebsiteId>" . $websiteId . "</WebsiteId>\n";
382
+
383
+ $xml .="</StoreDelete>\n";
384
+
385
+
386
+
387
+ $result = $this->postToChannelUnity($xml, "storeDelete");
388
+
389
+ } catch (Exception $e) {
390
+
391
+ Mage::logException($e);
392
  }
393
  }
394
+
395
  }
 
app/code/community/Camiloo/Channelunity/Model/Orders.php CHANGED
@@ -222,15 +222,18 @@ class Camiloo_Channelunity_Model_Orders extends Camiloo_Channelunity_Model_Abstr
222
 
223
  if (is_object($product)) {
224
 
225
- $product->setPrice(((string) $orderitem->Price) / $reverseRate);
226
 
227
  $item = Mage::getModel('sales/quote_item');
228
  $item->setQuote($quote)->setProduct($product);
229
  $item->setData('qty', (string) $orderitem->Quantity);
230
- $item->setCustomPrice((string) $orderitem->Price);
231
- $item->setOriginalCustomPrice((string) $orderitem->Price);
232
 
233
  $quote->addItem($item);
 
 
 
234
  }
235
  else {
236
  echo "<Info>Can't find SKU to add to quote ".((string) $orderitem->SKU)
@@ -277,14 +280,17 @@ class Camiloo_Channelunity_Model_Orders extends Camiloo_Channelunity_Model_Abstr
277
 
278
  if (is_object($product)) {
279
 
280
- $product->setPrice(((string) $orderitem->Price) / $reverseRate);
281
 
282
  $item = Mage::getModel('sales/quote_item');
283
  $item->setQuote($quote)->setProduct($product);
284
  $item->setData('qty', (string) $orderitem->Quantity);
285
- $item->setCustomPrice((string) $orderitem->Price);
286
- $item->setOriginalCustomPrice((string) $orderitem->Price);
287
  $quote->addItem($item);
 
 
 
288
  }
289
  else {
290
  echo "<Info>Can't find SKU to add to quote ".((string) $orderitem->SKU)."</Info>";
@@ -295,7 +301,6 @@ class Camiloo_Channelunity_Model_Orders extends Camiloo_Channelunity_Model_Abstr
295
  echo "<Info>Set Billing Address</Info>";
296
 
297
  $postcode = $this->fixEncoding((string) $order->ShippingInfo->PostalCode);
298
- $postcode = str_replace("-", "_", $postcode); // can throw exception if - in postcode
299
 
300
  $regionModel = Mage::getModel('directory/region')->loadByCode((string) $order->ShippingInfo->State, (string) $order->ShippingInfo->Country);
301
  $regionId = is_object($regionModel) ? $regionModel->getId() : ((string) $order->ShippingInfo->State);
@@ -341,10 +346,13 @@ class Camiloo_Channelunity_Model_Orders extends Camiloo_Channelunity_Model_Abstr
341
  'should_ignore_validation' => true
342
  );
343
 
344
- Mage::getSingleton('core/session')->setShippingPrice(((string) $order->ShippingInfo->ShippingPrice) / $reverseRate);
 
345
 
346
  // add the shipping address to the quote.
347
  $shippingAddress = $quote->getShippingAddress()->addData($shippingAddressData);
 
 
348
  /////////////////////////////////////////////
349
  $method = Mage::getModel('shipping/rate_result_method');
350
  $method->setCarrier('channelunitycustomrate');
@@ -366,7 +374,7 @@ class Camiloo_Channelunity_Model_Orders extends Camiloo_Channelunity_Model_Abstr
366
  $shippingAddress->setShippingMethod('channelunitycustomrate_channelunitycustomrate');
367
  $shippingAddress->setShippingDescription((string) $order->ShippingInfo->Service);
368
  $shippingAddress->setPaymentMethod('channelunitypayment');
369
-
370
  $quote->getPayment()->importData(array(
371
  'method' => 'channelunitypayment'
372
  ));
@@ -381,6 +389,7 @@ class Camiloo_Channelunity_Model_Orders extends Camiloo_Channelunity_Model_Abstr
381
  $currentstore = Mage::app()->getStore()->getId();
382
  // upgrade to admin permissions to avoid item qty not available issue
383
  Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID);
 
384
  $service->submitAll();
385
  $newOrder = $service->getOrder(); // returns full order object.
386
  // we're done; sign out of admin permission
@@ -435,6 +444,7 @@ class Camiloo_Channelunity_Model_Orders extends Camiloo_Channelunity_Model_Abstr
435
  * i.e. the invoice state is now changed to 'Paid'
436
  */
437
  $invoice->capture()->save();
 
438
 
439
  $newOrder->setTotalPaid($newOrder->getGrandTotal());
440
  $newOrder->setBaseTotalPaid($newOrder->getBaseGrandTotal());
@@ -648,90 +658,25 @@ class Camiloo_Channelunity_Model_Orders extends Camiloo_Channelunity_Model_Abstr
648
  }
649
 
650
  private function doSingleOrder($singleOrder, $newOrder) {
651
- /* // 1. Update shipping address
652
-
653
- $postcode = $this->fixEncoding((string) $singleOrder->ShippingInfo->PostalCode);
654
- $postcode = str_replace("-", "_", $postcode); // can throw exception if - in postcode
655
-
656
- $shippingId = $newOrder->getShippingAddress()->getId();
657
- $shipAddress = Mage::getModel('sales/order_address')->load($shippingId);
658
- $shipAddress->setFirstname($this->fixEncoding(
659
- $this->getFirstName((string) $singleOrder->ShippingInfo->RecipientName)));
660
- $shipAddress->setLastname($this->fixEncoding($this->getLastName((string) $singleOrder->ShippingInfo->RecipientName)));
661
- $shipAddress->setStreet((string) $this->fixEncoding(
662
- (string) $singleOrder->ShippingInfo->Address1
663
- ."\n".(string) $singleOrder->ShippingInfo->Address2
664
- ."\n".(string) $singleOrder->ShippingInfo->Address3));
665
- $shipAddress->setCity($this->fixEncoding((string) $singleOrder->ShippingInfo->City));
666
- $shipAddress->setPostcode($postcode);
667
- $shipAddress->setRegion((string) $singleOrder->ShippingInfo->State);
668
- $shipAddress->setRegionId((string) $singleOrder->ShippingInfo->State);
669
- $shipAddress->setCountryId((string) $singleOrder->ShippingInfo->Country);
670
- $shipAddress->setTelephone((string) $singleOrder->ShippingInfo->PhoneNumber);
671
- $shipAddress->save();
672
-
673
- // 2. Update billing address
674
- */
675
  // 3. Update order status
676
  $ordStatus = $this->CUOrderStatusToMagentoStatus((string) $singleOrder->OrderStatus);
677
 
678
  try {
679
- $newOrder->setData('state',$ordStatus);
680
-
681
  }
682
  catch (Exception $x1) {
683
 
684
  try {
685
- $newOrder->setState('closed' /*, 'closed', 'Order updated from ChannelUnity', false */);
686
 
 
 
687
  }
688
  catch (Exception $x2) {
689
  }
690
  }
691
- /*
692
- // 4. Update item prices and currency
693
-
694
- echo "<InfoUpdate>Order currency {$singleOrder->Currency}</InfoUpdate>";
695
- $newOrder->getStore()->setCurrentCurrencyCode((string) $singleOrder->Currency);
696
- $storeCurrency = $newOrder->getStore()->getBaseCurrencyCode();
697
- echo "<InfoUpdate>Store currency $storeCurrency</InfoUpdate>";
698
-
699
- $currencyObject = Mage::getModel('directory/currency');
700
- $reverseRate = $currencyObject->getResource()->getRate($storeCurrency, (string) $singleOrder->Currency);
701
 
702
- if ($reverseRate == "") {
703
- $reverseRate = 1.0;
704
- }
705
-
706
- echo "<ConversionRate>$reverseRate</ConversionRate>";
707
-
708
-
709
-
710
-
711
- $itemColl = $newOrder->getItemsCollection();
712
- foreach ($itemColl as $orderItem) {
713
-
714
- foreach ($singleOrder->OrderItems->Item as $orderitem1) {
715
-
716
- if (((string) $orderitem1->SKU) == $orderItem->getSku()) {
717
-
718
- // -- check what SKU is mapped to
719
-
720
- $priceTemp = ((string) $orderitem1->Price) / $reverseRate;
721
- $qtyTemp = (string) $orderitem1->Quantity;
722
-
723
- $orderItem->setPrice($priceTemp);
724
- $orderItem->setQtyOrdered($qtyTemp);
725
- $orderItem->setOriginalPrice($priceTemp);
726
- $orderItem->setRowTotal($priceTemp * $qtyTemp);
727
- $orderItem->setSubTotal($priceTemp * $qtyTemp);
728
-
729
- break;
730
- }
731
-
732
- }
733
- }
734
- */
735
  $newOrder->save();
736
  }
737
 
@@ -766,7 +711,31 @@ class Camiloo_Channelunity_Model_Orders extends Camiloo_Channelunity_Model_Abstr
766
  }
767
  }
768
  }
769
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
770
  public function doUpdate($dataArray) {
771
 
772
  foreach ($dataArray->Orders->Order as $order) {
222
 
223
  if (is_object($product)) {
224
 
225
+ $product->setPrice( $this->getDeTaxPrice((string) $orderitem->Price) / $reverseRate);
226
 
227
  $item = Mage::getModel('sales/quote_item');
228
  $item->setQuote($quote)->setProduct($product);
229
  $item->setData('qty', (string) $orderitem->Quantity);
230
+ $item->setCustomPrice($this->getDeTaxPrice((string) $orderitem->Price));
231
+ $item->setOriginalCustomPrice($this->getDeTaxPrice((string) $orderitem->Price));
232
 
233
  $quote->addItem($item);
234
+
235
+ $quote->save();
236
+ $item->save();
237
  }
238
  else {
239
  echo "<Info>Can't find SKU to add to quote ".((string) $orderitem->SKU)
280
 
281
  if (is_object($product)) {
282
 
283
+ $product->setPrice($this->getDeTaxPrice((string) $orderitem->Price) / $reverseRate);
284
 
285
  $item = Mage::getModel('sales/quote_item');
286
  $item->setQuote($quote)->setProduct($product);
287
  $item->setData('qty', (string) $orderitem->Quantity);
288
+ $item->setCustomPrice($this->getDeTaxPrice((string) $orderitem->Price));
289
+ $item->setOriginalCustomPrice($this->getDeTaxPrice((string) $orderitem->Price));
290
  $quote->addItem($item);
291
+
292
+ $quote->save();
293
+ $item->save();
294
  }
295
  else {
296
  echo "<Info>Can't find SKU to add to quote ".((string) $orderitem->SKU)."</Info>";
301
  echo "<Info>Set Billing Address</Info>";
302
 
303
  $postcode = $this->fixEncoding((string) $order->ShippingInfo->PostalCode);
 
304
 
305
  $regionModel = Mage::getModel('directory/region')->loadByCode((string) $order->ShippingInfo->State, (string) $order->ShippingInfo->Country);
306
  $regionId = is_object($regionModel) ? $regionModel->getId() : ((string) $order->ShippingInfo->State);
346
  'should_ignore_validation' => true
347
  );
348
 
349
+ Mage::getSingleton('core/session')->setShippingPrice(
350
+ ((string) $order->ShippingInfo->ShippingPrice) / $reverseRate);
351
 
352
  // add the shipping address to the quote.
353
  $shippingAddress = $quote->getShippingAddress()->addData($shippingAddressData);
354
+ $quote->getShippingAddress()->setData('should_ignore_validation', true);
355
+ $quote->getBillingAddress()->setData('should_ignore_validation', true);
356
  /////////////////////////////////////////////
357
  $method = Mage::getModel('shipping/rate_result_method');
358
  $method->setCarrier('channelunitycustomrate');
374
  $shippingAddress->setShippingMethod('channelunitycustomrate_channelunitycustomrate');
375
  $shippingAddress->setShippingDescription((string) $order->ShippingInfo->Service);
376
  $shippingAddress->setPaymentMethod('channelunitypayment');
377
+
378
  $quote->getPayment()->importData(array(
379
  'method' => 'channelunitypayment'
380
  ));
389
  $currentstore = Mage::app()->getStore()->getId();
390
  // upgrade to admin permissions to avoid item qty not available issue
391
  Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID);
392
+
393
  $service->submitAll();
394
  $newOrder = $service->getOrder(); // returns full order object.
395
  // we're done; sign out of admin permission
444
  * i.e. the invoice state is now changed to 'Paid'
445
  */
446
  $invoice->capture()->save();
447
+ Mage::dispatchEvent('sales_order_invoice_pay', array('invoice' => $invoice));
448
 
449
  $newOrder->setTotalPaid($newOrder->getGrandTotal());
450
  $newOrder->setBaseTotalPaid($newOrder->getBaseGrandTotal());
658
  }
659
 
660
  private function doSingleOrder($singleOrder, $newOrder) {
661
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
662
  // 3. Update order status
663
  $ordStatus = $this->CUOrderStatusToMagentoStatus((string) $singleOrder->OrderStatus);
664
 
665
  try {
666
+ $newOrder->setData('state', $ordStatus);
667
+ $newOrder->setData('status', $ordStatus);
668
  }
669
  catch (Exception $x1) {
670
 
671
  try {
 
672
 
673
+ $newOrder->setData('state', 'closed');
674
+ $newOrder->setData('status', 'closed');
675
  }
676
  catch (Exception $x2) {
677
  }
678
  }
 
 
 
 
 
 
 
 
 
 
679
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
680
  $newOrder->save();
681
  }
682
 
711
  }
712
  }
713
  }
714
+
715
+ public function getDeTaxPrice($price) {
716
+
717
+ $taxRate = 1;
718
+ $calc = Mage::getSingleton('tax/calculation');
719
+ $rates = $calc->getRatesForAllProductTaxClasses($calc->getRateRequest());
720
+
721
+ foreach ($rates as $class => $rate) {
722
+ $taxRate = $rate;
723
+
724
+ break;
725
+ }
726
+
727
+ if ($taxRate == 0) {
728
+
729
+ $taxRate = 1;
730
+ return $price;
731
+
732
+ }
733
+ else {
734
+
735
+ return $price / (100.0 + $taxRate) * 100.0;
736
+ }
737
+ }
738
+
739
  public function doUpdate($dataArray) {
740
 
741
  foreach ($dataArray->Orders->Order as $order) {
app/code/community/Camiloo/Channelunity/Model/Products.php CHANGED
@@ -1,679 +1,709 @@
1
  <?php
 
2
  /**
3
- * ChannelUnity connector for Magento Commerce
4
  *
5
  * @category Camiloo
6
  * @package Camiloo_Channelunity
7
  * @copyright Copyright (c) 2012 Camiloo Limited (http://www.camiloo.co.uk)
8
  * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
9
  */
10
- class Camiloo_Channelunity_Model_Products extends Camiloo_Channelunity_Model_Abstract
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  {
12
- protected $_collection = 'catalog/product';
13
- private $starttime;
14
- private $endtime;
15
- private $runtime = 0;
16
- private $beforeMemory;
17
- private $maxMemory;
18
- private $maxMemoryChar;
19
- private $maxruntime = 30;
20
- private $changeMemory = 0;
21
- private $upperLimit = 250;
22
- private $countCurr = 0;
23
- private $rangeNext = 0;
24
- private $premExit = false;
25
-
26
- public function postProductTypesToCU($request) {
27
-
28
- $url = (string) $request->URL;
29
- $putData = tmpfile();
30
- $bytes = 0;
31
-
32
- $messageToSend = "";
33
-
34
- $prodAttrEntType = Mage::getModel('catalog/product')
35
- ->getResource()->getEntityType()->getId();
36
-
37
- $attrColl = Mage::getResourceModel('eav/entity_attribute_set_collection')
38
- ->setEntityTypeFilter($prodAttrEntType);
39
-
40
- $messageToSend = "<URL>$url</URL>\n";
41
- $bytes = $bytes + fwrite($putData, $messageToSend);
42
-
43
- $messageToSend = "<ProductTypes>\n";
44
- $bytes = $bytes + fwrite($putData, $messageToSend);
45
- foreach ($attrColl as $attrModel) {
46
-
47
- $messageToSend = "<ProductType>\n";
48
- $bytes = $bytes + fwrite($putData, $messageToSend);
49
-
50
- $attribute_set_id = $attrModel->getData('attribute_set_id');
51
- $attribute_set_name = $attrModel->getData('attribute_set_name');
52
-
53
- $messageToSend = " <ProductTypeId>$attribute_set_id</ProductTypeId>\n";
 
 
 
 
 
 
 
 
 
54
  $bytes = $bytes + fwrite($putData, $messageToSend);
55
- $messageToSend = " <ProductTypeName><![CDATA[{$attribute_set_name}]]></ProductTypeName>\n";
56
  $bytes = $bytes + fwrite($putData, $messageToSend);
57
-
58
-
59
- $messageToSend = " <AttributeGroups>\n";
60
  $bytes = $bytes + fwrite($putData, $messageToSend);
61
-
62
- $product = Mage::getModel('catalog/product')->getCollection()
63
- ->addFieldToFilter('attribute_set_id', array('eq' => $attribute_set_id))
64
- ->addAttributeToSelect('entity_id');
65
- $product->getSelect()->limit(1);
66
- $product = $product->getFirstItem();
67
-
68
-
69
-
70
- $prodIdOfAttrSet = $product->getId();
71
- $atrGrpColl = Mage::getModel('eav/entity_attribute_group')->getCollection()
72
- ->addFieldToFilter('attribute_set_id', array('eq' => $attribute_set_id));
73
- foreach ($atrGrpColl as $atGrModel) {
74
- $attribute_group_name = $atGrModel->getData('attribute_group_name');
75
- $attribute_group_id = $atGrModel->getData('attribute_group_id');
76
-
77
- $messageToSend = " <AttributeGroup>\n";
78
- $bytes = $bytes + fwrite($putData, $messageToSend);
79
- $messageToSend = " <GroupName><![CDATA[{$attribute_group_name}]]></GroupName>\n";
80
- $bytes = $bytes + fwrite($putData, $messageToSend);
81
-
82
- $messageToSend = " <Attributes>\n";
83
- $bytes = $bytes + fwrite($putData, $messageToSend);
84
-
85
- if ($prodIdOfAttrSet != 0) {
86
- $product = Mage::getModel('catalog/product')->load($prodIdOfAttrSet);
87
-
88
- $collection = $product->getAttributes($attribute_group_id, false);
89
- foreach ($collection as $attribute) {
90
- $messageToSend = " <AttributeCode>" . $attribute->getAttributeCode() . "</AttributeCode>\n";
91
- $bytes = $bytes + fwrite($putData, $messageToSend);
92
- }
93
-
94
  }
95
-
96
- $messageToSend = " </Attributes>\n";
97
- $bytes = $bytes + fwrite($putData, $messageToSend);
98
-
99
- $messageToSend = " </AttributeGroup>\n";
100
- $bytes = $bytes + fwrite($putData, $messageToSend);
101
  }
102
-
103
- $messageToSend = " </AttributeGroups>\n";
104
  $bytes = $bytes + fwrite($putData, $messageToSend);
105
- $messageToSend = "</ProductType>\n";
 
106
  $bytes = $bytes + fwrite($putData, $messageToSend);
107
  }
108
-
109
- $messageToSend = "</ProductTypes>\n";
110
  $bytes = $bytes + fwrite($putData, $messageToSend);
111
-
112
- fseek($putData, 0);
113
- $senditnow = fread($putData, $bytes);
114
-
115
- $this->postToChannelUnity($senditnow, "ProductTypes");
116
-
117
- fclose($putData);
118
- }
119
-
120
- public function postAttributesToCU() {
121
-
122
- $putData = tmpfile();
123
- $bytes = 0;
124
-
125
- $messageToSend = "<ProductAttributes>\n";
126
-
127
  $bytes = $bytes + fwrite($putData, $messageToSend);
128
- $product = Mage::getModel('catalog/product');
129
- $attributes = Mage::getResourceModel('eav/entity_attribute_collection')
130
- ->setEntityTypeFilter($product->getResource()->getTypeId())
131
- ->load(false);
132
-
133
- foreach($attributes as $attribute){
134
-
135
- $attr = $attribute->getData('attribute_code');
136
-
137
- if ($attr != 'name' && $attr != 'description' && $attr != 'sku' && $attr != 'price' && $attr != 'qty' && $attr != 'stock_item') {
138
-
139
- $attrType = trim($attribute->getBackendType());
140
- $friendlyName = trim($attribute->getFrontendLabel());
141
-
142
- $messageToSend = " <Attribute><Name>$attr</Name><Type>$attrType</Type>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
143
  <FriendlyName><![CDATA[{$friendlyName}]]></FriendlyName></Attribute>\n";
144
-
145
- $bytes = $bytes + fwrite($putData, $messageToSend);
146
- }
147
-
148
- }
149
-
150
- $messageToSend = "</ProductAttributes>\n";
151
- $bytes = $bytes + fwrite($putData, $messageToSend);
152
-
153
- fseek($putData, 0);
154
- $senditnow = fread($putData, $bytes);
155
- fclose($putData);
156
- $result = $this->postToChannelUnity($senditnow, "ProductAttributes");
157
- $xml = simplexml_load_string($result, 'SimpleXMLElement', LIBXML_NOCDATA);
158
-
159
- if (isset($xml->Status)) {
160
- return $xml->Status;
161
- }
162
- else if (isset($xml->status)) {
163
- return $xml->status;
164
- }
165
- else {
166
- return "Error - unexpected response";
167
  }
168
  }
169
-
170
- public function generateCuXmlForSingleProduct($productId, $storeId, $reduceStockBy = 0) {
171
- $productXml = "";
172
- $bNeedCustomOptionProducts = false; // custom options needed?
173
- $skuList = array(); // SKUs of the custom option child products
174
- $customOptionAttrs = array();
175
- $customOptionsData = array();
176
-
177
- $product = Mage::getModel('catalog/product');
178
- $product->setStoreId($storeId)->load($productId);
179
-
180
- try {
181
- $imageUrl = $product->getImageUrl();
182
- } catch (Exception $e) {
183
- $imageUrl = '';
184
- }
185
-
186
- $stock = Mage::getModel('cataloginventory/stock_item')->loadByProduct($product->getId());
187
- $qty = $stock->getData('qty') - $reduceStockBy;
188
-
189
- $catids = implode(',', $product->getCategoryIds());
190
- $categories = $product->getCategoryIds();
191
- $catnames = "";
192
-
193
- foreach ($categories as $k => $_category_id) {
194
- $_category = Mage::getModel('catalog/category')->load($_category_id);
195
- $catnames .= ($_category->getName()) . ", ";
196
- }
197
-
198
- $attributeSetModel = Mage::getModel("eav/entity_attribute_set");
199
- $attributeSetModel->load($product->getData('attribute_set_id'));
200
- $attributeSetName = $attributeSetModel->getAttributeSetName();
201
-
202
- $productXml = "<Product>\n";
203
- $productXml .= " <RemoteId>".$product->getId()."</RemoteId>\n";
204
- $productXml .= " <ProductType><![CDATA[".$attributeSetName." ]]></ProductType>\n";
205
- $productXml .= " <Title><![CDATA[{$product->getData('name')} ]]></Title>\n";
206
- $productXml .= " <Description><![CDATA[{$product->getData('description')} ]]></Description>\n";
207
- $productXml .= " <SKU><![CDATA[{$product->getData('sku')}]]></SKU>\n";
208
- $productXml .= " <Price>{$product->getData('price')}</Price>\n";
209
- $productXml .= " <Quantity>{$qty}</Quantity>\n";
210
- $productXml .= " <Category>{$catids}</Category>\n";
211
- $productXml .= " <CategoryName><![CDATA[{$catnames} ]]></CategoryName>\n";
212
- $productXml .= " <Image><![CDATA[{$imageUrl}]]></Image>\n";
213
-
214
- // Add associated/child product references if applicable
215
- $productXml .= " <RelatedSKUs>\n";
216
-
217
- $variationXml = " <Variations>\n";
218
-
219
- if ($product->getData("type_id") == 'configurable') {
220
-
221
- $childProducts = Mage::getModel('catalog/product_type_configurable')
222
- ->getUsedProducts(null, $product);
223
-
224
- foreach ($childProducts as $cp) {
225
-
226
- $productXml .= " <SKU><![CDATA[{$cp->getData('sku')}]]></SKU>\n";
227
- }
228
-
229
- $confAttributes = $product->getTypeInstance(true)->getConfigurableAttributesAsArray($product);
230
-
231
- // Get the attribute(s) which vary
232
- if (is_array($confAttributes)) {
233
- foreach ($confAttributes as $cattr) {
234
- $cattr = serialize($cattr);
235
-
236
- $findTemp = "\"attribute_code\";";
237
-
238
- $cattr = explode($findTemp, $cattr);
239
-
240
- if (isset($cattr[1])) {
241
-
242
- $cattr = explode("\"", $cattr[1]);
243
-
244
- if (isset($cattr[1])) {
245
-
246
- $variationXml .= "<Variation><![CDATA[{$cattr[1]}]]></Variation>\n";
247
-
248
- }
249
- }
250
- }
251
- }
252
-
253
- }
254
- else if ($product->getTypeId() == 'grouped') {
255
-
256
- // Do we need to do variations?
257
-
258
- $childProducts = $product->getTypeInstance(true)->getAssociatedProducts($product);
259
- foreach ($childProducts as $cp) {
260
-
261
- $productXml .= " <SKU><![CDATA[{$cp->getData('sku')}]]></SKU>\n";
262
- }
263
- }
264
- else if ($product->getData('has_options') == 1) {
265
- $bNeedCustomOptionProducts = true;
266
-
267
- // Product has custom options
268
-
269
- foreach ($product->getOptions() as $o) {
270
- $optionType = $o->getType();
271
-
272
- // Look at only drop down boxes or radio buttons
273
-
274
- if (($optionType == 'drop_down' || $optionType == 'radio')
275
- && $o->getData("is_require") == 1) {
276
-
277
- $optTitle = $o->getData('title');
278
- $optTitle = "custom_".ereg_replace("[^A-Za-z0-9_]", "", str_replace(" ", "_", $optTitle));
279
-
280
- $customOptionsData[$optTitle] = array();
281
-
282
- $variationXml .= " <Variation><![CDATA[{$optTitle}]]></Variation>\n";
283
- $customOptionAttrs[] = $optTitle;
284
-
285
- $values = $o->getValues();
286
-
287
- if (count($skuList) == 0) {
288
-
289
- foreach ($values as $k => $v) {
290
-
291
- $skuList[] = $product->getData('sku')."-".$v->getData('sku');
292
-
293
- $customOptionsData[count($customOptionAttrs)][$v->getData('sku')] = array();
294
- $customOptionsData[count($customOptionAttrs)][$v->getData('sku')]["title"] = $v->getData('title');
295
- $customOptionsData[count($customOptionAttrs)][$v->getData('sku')]["price"] = $v->getData('price');
296
- $customOptionsData[count($customOptionAttrs)][$v->getData('sku')]["price_type"] = $v->getData('price_type');
297
- }
298
-
299
- }
300
- else {
301
- // Take a copy of the current SKU list
302
- // append all the combinations
303
-
304
- $tempSkuList = array();
305
- foreach ($values as $k => $v) {
306
-
307
- $tempSkuList[] = $v->getData('sku');
308
-
309
- $customOptionsData[count($customOptionAttrs)][$v->getData('sku')] = array();
310
- $customOptionsData[count($customOptionAttrs)][$v->getData('sku')]["title"] = $v->getData('title');
311
- $customOptionsData[count($customOptionAttrs)][$v->getData('sku')]["price"] = $v->getData('price');
312
- $customOptionsData[count($customOptionAttrs)][$v->getData('sku')]["price_type"] = $v->getData('price_type');
313
- }
314
-
315
- $newSkuList = array();
316
-
317
- foreach ($skuList as $oldSku) {
318
-
319
- foreach ($tempSkuList as $newSku) {
320
-
321
- $newSkuList[] = $oldSku."-".$newSku;
322
- }
323
- }
324
-
325
- $skuList = $newSkuList;
326
- }
327
-
328
- }
329
- }
330
-
331
- // Build up the SKU combinations for each combination of options
332
- foreach ($skuList as $relsku) {
333
-
334
- $productXml .= " <SKU><![CDATA[{$relsku}]]></SKU>\n";
335
- }
336
-
337
- }
338
-
339
- $variationXml .= " </Variations>\n";
340
- $productXml .= " </RelatedSKUs>\n";
341
- $productXml .= $variationXml;
342
-
343
- $productXml .= " <Custom>\n";
344
-
345
- // Enumerate all other attribute values
346
- $productXml .= $this->enumerateCustomAttributesForProduct($product);
347
-
348
- $productXml .= " </Custom>\n";
349
- $productXml .= "</Product>\n";
350
-
351
- // ============ Now generate product elements for all possible custom options ============
352
- $idIncrement = 1000000;
353
-
354
- if ($bNeedCustomOptionProducts) {
355
-
356
- foreach ($skuList as $customSku) {
357
-
358
- $skuParts = explode("-", str_replace($product->getData('sku'), "temp", $customSku));
359
-
360
- $productXml .= "<Product>\n";
361
- $productXml .= " <RemoteId>".(($idIncrement++) + $product->getId())."</RemoteId>\n";
362
- $productXml .= " <ProductType><![CDATA[".$attributeSetName." ]]></ProductType>\n";
363
- $productXml .= " <Title><![CDATA[{$product->getData('name')} ]]></Title>\n";
364
- $productXml .= " <Description><![CDATA[{$product->getData('description')} ]]></Description>\n";
365
- $productXml .= " <SKU><![CDATA[{$customSku}]]></SKU>\n";
366
- $productXml .= " <Quantity>{$qty}</Quantity>\n";
367
- $productXml .= " <Category>{$catids}</Category>\n";
368
- $productXml .= " <CategoryName><![CDATA[{$catnames} ]]></CategoryName>\n";
369
- $productXml .= " <Image><![CDATA[{$imageUrl}]]></Image>\n";
370
- $productXml .= " <RelatedSKUs> </RelatedSKUs> <Variations> </Variations>\n";
371
- $productXml .= " <Custom>\n";
372
-
373
- // Enumerate all other attribute values
374
- $productXml .= $this->enumerateCustomAttributesForProduct($product);
375
-
376
- $basePrice = $product->getData('price');
377
- $extraPrice = 0.00;
378
-
379
- $indexTemp = 1;
380
- for ( ; $indexTemp < count($skuParts); ) {
381
- $part = $skuParts[$indexTemp];
382
-
383
- $keycust = $customOptionAttrs[$indexTemp-1];
384
-
385
- $custValue = $customOptionsData[$indexTemp][$part]['title'];
386
-
387
- $priceExtra = $customOptionsData[$indexTemp][$part]['price'];
388
- $priceType = $customOptionsData[$indexTemp][$part]['price_type'];
389
-
390
- if ($priceType == "fixed") {
391
-
392
- $extraPrice += (double)$priceExtra;
393
- }
394
- else if ($priceType == "percent") {
395
-
396
- $extraPrice += $basePrice * (100.0 + $priceExtra)/100.0;
397
- }
398
-
399
- $productXml .= " <$keycust><![CDATA[".$custValue."]]></$keycust>\n";
400
-
401
- $indexTemp++;
402
- }
403
-
404
- $basePrice += $extraPrice; // custom options have prices attached
405
-
406
- $productXml .= " </Custom>\n";
407
-
408
-
409
- $productXml .= " <Price>$basePrice</Price>\n";
410
-
411
- $productXml .= "</Product>\n";
412
- }
413
- }
414
- // =======================================================================================
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
415
  unset($product);
416
-
417
- return $productXml;
418
  }
419
-
420
- public function enumerateCustomAttributesForProduct($product) {
421
- $productXml = "";
422
-
423
- $attributeNames = array_keys($product->getData());
424
-
425
- foreach ($attributeNames as $k => $attr) {
426
-
427
- if ($attr != 'name' && $attr != 'description' && $attr != 'sku'
428
- && $attr != 'price' && $attr != 'qty'
429
- && $attr != 'stock_item' && $attr != 'tier_price') {
430
-
431
- if ($attribute = $product->getResource()->getAttribute($attr)) {
432
-
433
- $myval = $product->getData($attr);
434
-
435
- if (is_array($myval)) {
436
- $myval = serialize($myval);
437
- }
438
-
439
- if (is_object($attribute)) {
440
-
441
- $prodDataValue = $attribute->getSource()
442
- ->getOptionText($myval);
443
-
444
- if ($prodDataValue == '') {
445
-
446
- $prodDataValue = $myval;
447
- }
448
- }
449
- else {
 
 
450
  $prodDataValue = $myval;
451
  }
452
- } else {
453
- $prodDataValue = $product->getData($attr);
454
  }
455
-
456
- if (is_object($prodDataValue)) {
457
- if ('Varien_Object' == get_class($prodDataValue)) {
458
-
459
- $prodDataValue = $prodDataValue->toXml();
460
- }
461
  }
462
- if (is_array($prodDataValue)) {
463
-
464
- $prodDataValue = $product->getData($attr);
465
- $productXml .= " <$attr><![CDATA[$prodDataValue]]></$attr>\n";
 
 
 
 
 
466
  }
467
- else {
468
-
469
- if (!is_object($prodDataValue)) {
470
-
471
- $prodDataValue = str_replace("<![CDATA[", "", $prodDataValue);
472
- $prodDataValue = str_replace("]]>", "", $prodDataValue);
473
- $productXml .= " <$attr><![CDATA[".$prodDataValue."]]></$attr>\n";
474
-
475
- } else if ('Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Type_Configurable_Attribute_Collection'
476
- == get_class($prodDataValue)) {
477
- $productXml .= " <$attr><![CDATA[Mage_Core_Model_Mysql4_Collection_Abstract]]></$attr>\n";
478
- }
 
 
 
 
 
 
 
479
  }
480
  }
481
  }
482
- return $productXml;
483
- }
484
-
485
- public function generateCuXmlForProductEcho($args) {
486
- echo $this->generateCuXmlForProduct($args);
487
  }
488
-
489
- public function generateCuXmlForProduct($args) {
490
- $productXml = '';
491
- $this->countCurr++;
492
-
493
- $this->maxMemory = $this->return_bytes(ini_get('memory_limit'));
494
-
495
- if ($this->runtime < $this->maxruntime
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
496
  && (memory_get_peak_usage() + $this->changeMemory) < $this->maxMemory
497
- && $this->countCurr <= $this->upperLimit)
498
- {
499
- $row = $args['row'];
500
- $this->rangeNext = $row["entity_id"] + 1;
501
-
502
- $productXml .= $this->generateCuXmlForSingleProduct($row["entity_id"], $args["storeId"]);
503
-
504
- // after....
505
- $this->endtime = $this->microtime_float();
506
- $this->runtime = round($this->endtime - $this->starttime);
507
-
508
- $tmpval = memory_get_peak_usage() - $this->beforeMemory;
509
- if ($tmpval > $this->changeMemory) {
510
- $this->changeMemory = $tmpval;
511
- }
512
-
513
- } else {
514
-
515
- $this->premExit = true; // i.e. exited before got through all prods
516
-
517
  }
518
-
519
- return $productXml;
520
- }
521
-
522
- public function microtime_float() {
523
- list ($msec, $sec) = explode(' ', microtime());
524
- $microtime = (float)$msec + (float)$sec;
525
- return $microtime;
526
  }
527
-
528
- function return_bytes($val) {
529
- $val = trim($val);
530
- $last = strtolower($val[strlen($val)-1]);
531
- switch($last) {
532
- // The 'G' modifier is available since PHP 5.1.0
533
- case 'g':
534
- $val *= 1024;
535
- case 'm':
536
- $val *= 1024;
537
- case 'k':
538
- $val *= 1024;
539
- }
540
-
541
- return $val;
 
 
 
 
 
 
 
 
542
  }
543
-
544
- public function doSetValue($request) {
545
- $storeId = (string) $request->StoreviewId;
546
- $fieldName = (string) $request->FieldName;
547
- $fieldValue = (string) $request->FieldValue;
548
- $sku = (string) $request->SKU;
549
-
550
- $collectionOfProduct = Mage::getModel($this->_collection)->getCollection()->addStoreFilter($storeId);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
551
  $collectionOfProduct->setPageSize(1);
552
  $collectionOfProduct->setCurPage(1);
553
- $collectionOfProduct->addFieldToFilter('sku', $sku);
554
- $product = $collectionOfProduct->getFirstItem();
555
-
556
- // set an attribute for the product
557
- $product->setData($fieldName, $fieldValue);
558
- $product->save();
559
- }
560
-
561
- /**
562
- * Return a set of product data to CU.
563
- */
564
- public function doRead($request) {
565
- $rangeFrom = (string) $request->RangeFrom;
566
- $rangeTo = (string) $request->RangeTo;
567
- $storeId = (string) $request->StoreviewId;
568
-
569
- $this->starttime = $this->microtime_float();
570
- $this->endtime = $this->microtime_float();
571
- $this->runtime = round($this->endtime - $this->starttime);
572
- $this->beforeMemory = memory_get_peak_usage();
573
- $this->maxMemory = ini_get('memory_limit');
574
- $this->maxMemoryChar = substr($this->maxMemory,strlen($this->maxMemory)-1,1);
575
-
576
- echo "<Products>\n";
577
-
578
- try {
579
-
580
- // get the highest product ID
581
- if (version_compare(Mage::getVersion(), "1.6.0.0", ">=")
582
- && class_exists("Mage_Catalog_Model_Resource_Product_Collection")) {
583
- $collectionOfProduct = Mage::getModel('channelunity/collection')->addStoreFilter($storeId);
584
- }
585
- else {
586
- $collectionOfProduct = Mage::getModel('catalog/product')->getCollection()->addStoreFilter($storeId);
587
- }
588
- $collectionOfProduct->setOrder('entity_id', 'DESC');
589
- $collectionOfProduct->setPageSize(1);
590
- $collectionOfProduct->setCurPage(1);
591
- $totp = $collectionOfProduct->getFirstItem();
592
- $totp = $totp->getEntityId();
593
-
594
- if (version_compare(Mage::getVersion(), "1.6.0.0", ">=")
595
  && class_exists("Mage_Catalog_Model_Resource_Product_Collection")) {
596
- $collectionOfProduct = Mage::getModel('channelunity/collection')->addStoreFilter($storeId);
597
- }
598
- else {
599
- $collectionOfProduct = Mage::getModel('catalog/product')->getCollection()->addStoreFilter($storeId);
600
- }
601
- $totalNumProducts = $this->executeQueryScalar(str_replace("SELECT", "SELECT count(*) as count_cu, ", $collectionOfProduct->getSelect()), 'count_cu');
602
-
603
- $collectionOfProduct->addAttributeToFilter("entity_id", array('gteq' => $rangeFrom))
 
 
 
 
 
604
  ->setOrder('entity_id', 'ASC');
605
-
606
- // monitor memory and max exec
607
- if ($this->maxMemoryChar == "M") {
608
- $this->maxMemory = str_replace("M", "", $this->maxMemory);
609
- $this->maxMemory = $this->maxMemory * 1024 * 1024;
610
- } else if ($this->maxMemoryChar == "G") {
611
- $this->maxMemory = str_replace("G", "", $this->maxMemory);
612
- $this->maxMemory = $this->maxMemory * 1024 * 1024 * 1024;
613
- }
614
-
615
- if ($this->maxMemory < 100) {
616
- $this->maxMemory = 10000000000;
617
- }
618
-
619
- $query = str_replace("INNER JOIN", "LEFT JOIN", $collectionOfProduct->getSelect());
620
-
621
- echo "<Query><![CDATA[$query]]></Query>\n";
622
-
623
- try {
624
-
625
- Mage::getSingleton('core/resource_iterator')->walk($query,
626
- array(array($this, 'generateCuXmlForProductEcho')),
627
- array('storeId' => $storeId),
628
- $collectionOfProduct->getSelect()->getAdapter());
629
-
630
- }
631
- catch (Exception $x1) {
632
- Mage::getSingleton('core/resource_iterator')->walk($collectionOfProduct->getSelect(),
633
- array(array($this, 'generateCuXmlForProductEcho')),
634
- array('storeId' => $storeId));
635
- }
636
-
637
- // Let the cloud know where to start from the next time it calls
638
- // for product data
639
-
640
- if ($this->rangeNext <= $totp) {
641
- echo "<RangeNext>".$this->rangeNext."</RangeNext>\n";
642
- } else {
643
- // Start from beginning next time
644
- echo "<RangeNext>0</RangeNext>\n";
645
- }
646
-
647
- echo "<TotalProducts>$totalNumProducts</TotalProducts>\n";
648
  }
649
- catch (Exception $x) {
650
- echo "<Error><![CDATA[".$x->getTraceAsString()."]]></Error>\n";
 
651
  }
652
- echo "</Products>\n";
653
- }
654
-
655
- private function executeQuery($sql) {
656
- $db = Mage::getSingleton("core/resource")->getConnection("core_write");
657
-
658
- $result = $db->query($sql);
659
-
660
- $resultArray = array();
661
-
662
- foreach ($result as $row) {
663
-
664
- $resultArray[] = $row;
665
  }
666
-
667
- return $resultArray;
668
- }
669
- private function executeQueryScalar($sql, $column) {
670
- $result = $this->executeQuery($sql);
671
-
672
- foreach ($result as $row) {
673
- return $row[$column];
 
674
  }
675
- return -1;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
676
  }
 
 
677
  }
678
-
679
- ?>
 
 
 
 
 
 
 
 
 
 
 
1
  <?php
2
+
3
  /**
4
+ * ChannelUnity connector for Magento Commerce
5
  *
6
  * @category Camiloo
7
  * @package Camiloo_Channelunity
8
  * @copyright Copyright (c) 2012 Camiloo Limited (http://www.camiloo.co.uk)
9
  * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
10
  */
11
+ class Camiloo_Channelunity_Model_Products extends Camiloo_Channelunity_Model_Abstract
12
+ {
13
+
14
+ protected $_collection = 'catalog/product';
15
+ private $starttime;
16
+ private $endtime;
17
+ private $runtime = 0;
18
+ private $beforeMemory;
19
+ private $maxMemory;
20
+ private $maxMemoryChar;
21
+ private $maxruntime = 30;
22
+ private $changeMemory = 0;
23
+ private $upperLimit = 250;
24
+ private $countCurr = 0;
25
+ private $rangeNext = 0;
26
+ private $premExit = false;
27
+
28
+ public function postProductTypesToCU($request)
29
  {
30
+
31
+ $url = (string) $request->URL;
32
+ $putData = tmpfile();
33
+ $bytes = 0;
34
+
35
+ $messageToSend = "";
36
+
37
+ $prodAttrEntType = Mage::getModel('catalog/product')
38
+ ->getResource()->getEntityType()->getId();
39
+
40
+ $attrColl = Mage::getResourceModel('eav/entity_attribute_set_collection')
41
+ ->setEntityTypeFilter($prodAttrEntType);
42
+
43
+ $messageToSend = "<URL>$url</URL>\n";
44
+ $bytes = $bytes + fwrite($putData, $messageToSend);
45
+
46
+ $messageToSend = "<ProductTypes>\n";
47
+ $bytes = $bytes + fwrite($putData, $messageToSend);
48
+ foreach ($attrColl as $attrModel) {
49
+
50
+ $messageToSend = "<ProductType>\n";
51
+ $bytes = $bytes + fwrite($putData, $messageToSend);
52
+
53
+ $attribute_set_id = $attrModel->getData('attribute_set_id');
54
+ $attribute_set_name = $attrModel->getData('attribute_set_name');
55
+
56
+ $messageToSend = " <ProductTypeId>$attribute_set_id</ProductTypeId>\n";
57
+ $bytes = $bytes + fwrite($putData, $messageToSend);
58
+ $messageToSend = " <ProductTypeName><![CDATA[{$attribute_set_name}]]></ProductTypeName>\n";
59
+ $bytes = $bytes + fwrite($putData, $messageToSend);
60
+
61
+
62
+ $messageToSend = " <AttributeGroups>\n";
63
+ $bytes = $bytes + fwrite($putData, $messageToSend);
64
+
65
+ $product = Mage::getModel('catalog/product')->getCollection()
66
+ ->addFieldToFilter('attribute_set_id', array('eq' => $attribute_set_id))
67
+ ->addAttributeToSelect('entity_id');
68
+ $product->getSelect()->limit(1);
69
+ $product = $product->getFirstItem();
70
+
71
+
72
+
73
+ $prodIdOfAttrSet = $product->getId();
74
+ $atrGrpColl = Mage::getModel('eav/entity_attribute_group')->getCollection()
75
+ ->addFieldToFilter('attribute_set_id', array('eq' => $attribute_set_id));
76
+ foreach ($atrGrpColl as $atGrModel) {
77
+ $attribute_group_name = $atGrModel->getData('attribute_group_name');
78
+ $attribute_group_id = $atGrModel->getData('attribute_group_id');
79
+
80
+ $messageToSend = " <AttributeGroup>\n";
81
  $bytes = $bytes + fwrite($putData, $messageToSend);
82
+ $messageToSend = " <GroupName><![CDATA[{$attribute_group_name}]]></GroupName>\n";
83
  $bytes = $bytes + fwrite($putData, $messageToSend);
84
+
85
+ $messageToSend = " <Attributes>\n";
 
86
  $bytes = $bytes + fwrite($putData, $messageToSend);
87
+
88
+ if ($prodIdOfAttrSet != 0) {
89
+ $product = Mage::getModel('catalog/product')->load($prodIdOfAttrSet);
90
+
91
+ $collection = $product->getAttributes($attribute_group_id, false);
92
+ foreach ($collection as $attribute) {
93
+ $messageToSend = " <AttributeCode>" . $attribute->getAttributeCode() . "</AttributeCode>\n";
94
+ $bytes = $bytes + fwrite($putData, $messageToSend);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
95
  }
 
 
 
 
 
 
96
  }
97
+
98
+ $messageToSend = " </Attributes>\n";
99
  $bytes = $bytes + fwrite($putData, $messageToSend);
100
+
101
+ $messageToSend = " </AttributeGroup>\n";
102
  $bytes = $bytes + fwrite($putData, $messageToSend);
103
  }
104
+
105
+ $messageToSend = " </AttributeGroups>\n";
106
  $bytes = $bytes + fwrite($putData, $messageToSend);
107
+ $messageToSend = "</ProductType>\n";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
108
  $bytes = $bytes + fwrite($putData, $messageToSend);
109
+ }
110
+
111
+ $messageToSend = "</ProductTypes>\n";
112
+ $bytes = $bytes + fwrite($putData, $messageToSend);
113
+
114
+ fseek($putData, 0);
115
+ $senditnow = fread($putData, $bytes);
116
+
117
+ $this->postToChannelUnity($senditnow, "ProductTypes");
118
+
119
+ fclose($putData);
120
+ }
121
+
122
+ public function postAttributesToCU()
123
+ {
124
+
125
+ $putData = tmpfile();
126
+ $bytes = 0;
127
+
128
+ $messageToSend = "<ProductAttributes>\n";
129
+
130
+ $bytes = $bytes + fwrite($putData, $messageToSend);
131
+ $product = Mage::getModel('catalog/product');
132
+ $attributes = Mage::getResourceModel('eav/entity_attribute_collection')
133
+ ->setEntityTypeFilter($product->getResource()->getTypeId())
134
+ ->load(false);
135
+
136
+ foreach ($attributes as $attribute) {
137
+
138
+ $attr = $attribute->getData('attribute_code');
139
+
140
+ if ($attr != 'name' && $attr != 'description' && $attr != 'sku' && $attr != 'price' && $attr != 'qty' && $attr != 'stock_item') {
141
+
142
+ $attrType = trim($attribute->getBackendType());
143
+ $friendlyName = trim($attribute->getFrontendLabel());
144
+
145
+ $messageToSend = " <Attribute><Name>$attr</Name><Type>$attrType</Type>
146
  <FriendlyName><![CDATA[{$friendlyName}]]></FriendlyName></Attribute>\n";
147
+
148
+ $bytes = $bytes + fwrite($putData, $messageToSend);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
149
  }
150
  }
151
+
152
+ $messageToSend = "</ProductAttributes>\n";
153
+ $bytes = $bytes + fwrite($putData, $messageToSend);
154
+
155
+ fseek($putData, 0);
156
+ $senditnow = fread($putData, $bytes);
157
+ fclose($putData);
158
+ $result = $this->postToChannelUnity($senditnow, "ProductAttributes");
159
+ $xml = simplexml_load_string($result, 'SimpleXMLElement', LIBXML_NOCDATA);
160
+
161
+ if (isset($xml->Status)) {
162
+ return $xml->Status;
163
+ } else if (isset($xml->status)) {
164
+ return $xml->status;
165
+ } else {
166
+ return "Error - unexpected response";
167
+ }
168
+ }
169
+
170
+ public function generateCuXmlForSingleProduct($productId, $storeId, $reduceStockBy = 0)
171
+ {
172
+ $productXml = "";
173
+ $bNeedCustomOptionProducts = false; // custom options needed?
174
+ $skuList = array(); // SKUs of the custom option child products
175
+ $customOptionAttrs = array();
176
+ $customOptionsData = array();
177
+
178
+ $product = Mage::getModel('catalog/product');
179
+ $product->setStoreId($storeId)->load($productId);
180
+
181
+ $skipProduct = Mage::getModel('channelunity/products')->skipProduct($product);
182
+
183
+ if(!$skipProduct)
184
+ {
185
+ try {
186
+ $imageUrl = $product->getImageUrl();
187
+ } catch (Exception $e) {
188
+ $imageUrl = '';
189
+ }
190
+
191
+ $stock = Mage::getModel('cataloginventory/stock_item')->loadByProduct($product->getId());
192
+ $qty = $stock->getData('qty') - $reduceStockBy;
193
+
194
+ $catids = implode(',', $product->getCategoryIds());
195
+ $categories = $product->getCategoryIds();
196
+ $catnames = "";
197
+
198
+ foreach ($categories as $k => $_category_id) {
199
+ $_category = Mage::getModel('catalog/category')->load($_category_id);
200
+ $catnames .= ($_category->getName()) . ", ";
201
+ }
202
+
203
+ $attributeSetModel = Mage::getModel("eav/entity_attribute_set");
204
+ $attributeSetModel->load($product->getData('attribute_set_id'));
205
+ $attributeSetName = $attributeSetModel->getAttributeSetName();
206
+
207
+ $productXml = "<Product>\n";
208
+ $productXml .= " <RemoteId>" . $product->getId() . "</RemoteId>\n";
209
+ $productXml .= " <ProductType><![CDATA[" . $attributeSetName . " ]]></ProductType>\n";
210
+ $productXml .= " <Title><![CDATA[{$product->getName()} ]]></Title>\n";
211
+ $productXml .= " <Description><![CDATA[{$product->getData('description')} ]]></Description>\n";
212
+ $productXml .= " <SKU><![CDATA[{$product->getData('sku')}]]></SKU>\n";
213
+ $productXml .= " <Price>{$product->getData('price')}</Price>\n";
214
+ $productXml .= " <Quantity>{$qty}</Quantity>\n";
215
+ $productXml .= " <Category>{$catids}</Category>\n";
216
+ $productXml .= " <CategoryName><![CDATA[{$catnames} ]]></CategoryName>\n";
217
+ $productXml .= " <Image><![CDATA[{$imageUrl}]]></Image>\n";
218
+
219
+ // Add associated/child product references if applicable
220
+ $productXml .= " <RelatedSKUs>\n";
221
+
222
+ $variationXml = " <Variations>\n";
223
+
224
+ if ($product->getData("type_id") == 'configurable') {
225
+
226
+ $childProducts = Mage::getModel('catalog/product_type_configurable')
227
+ ->getUsedProducts(null, $product);
228
+
229
+ foreach ($childProducts as $cp) {
230
+
231
+ $productXml .= " <SKU><![CDATA[{$cp->getData('sku')}]]></SKU>\n";
232
+ }
233
+
234
+ $confAttributes = $product->getTypeInstance(true)->getConfigurableAttributesAsArray($product);
235
+
236
+ // Get the attribute(s) which vary
237
+ if (is_array($confAttributes)) {
238
+ foreach ($confAttributes as $cattr) {
239
+ $cattr = serialize($cattr);
240
+
241
+ $findTemp = "\"attribute_code\";";
242
+
243
+ $cattr = explode($findTemp, $cattr);
244
+
245
+ if (isset($cattr[1])) {
246
+
247
+ $cattr = explode("\"", $cattr[1]);
248
+
249
+ if (isset($cattr[1])) {
250
+
251
+ $variationXml .= "<Variation><![CDATA[{$cattr[1]}]]></Variation>\n";
252
+ }
253
+ }
254
+ }
255
+ }
256
+ } else if ($product->getTypeId() == 'grouped') {
257
+
258
+ // Do we need to do variations?
259
+
260
+ $childProducts = $product->getTypeInstance(true)->getAssociatedProducts($product);
261
+ foreach ($childProducts as $cp) {
262
+
263
+ $productXml .= " <SKU><![CDATA[{$cp->getData('sku')}]]></SKU>\n";
264
+ }
265
+ } else if ($product->getData('has_options') == 1) {
266
+ $bNeedCustomOptionProducts = true;
267
+
268
+ // Product has custom options
269
+
270
+ foreach ($product->getOptions() as $o) {
271
+ $optionType = $o->getType();
272
+
273
+ // Look at only drop down boxes or radio buttons
274
+
275
+ if (($optionType == 'drop_down' || $optionType == 'radio')
276
+ && $o->getData("is_require") == 1) {
277
+
278
+ $optTitle = $o->getData('title');
279
+ $optTitle = "custom_" . ereg_replace("[^A-Za-z0-9_]", "", str_replace(" ", "_", $optTitle));
280
+
281
+ $customOptionsData[$optTitle] = array();
282
+
283
+ $variationXml .= " <Variation><![CDATA[{$optTitle}]]></Variation>\n";
284
+ $customOptionAttrs[] = $optTitle;
285
+
286
+ $values = $o->getValues();
287
+
288
+ if (count($skuList) == 0) {
289
+
290
+ foreach ($values as $k => $v) {
291
+
292
+ $skuList[] = $product->getData('sku') . "-" . $v->getData('sku');
293
+
294
+ $customOptionsData[count($customOptionAttrs)][$v->getData('sku')] = array();
295
+ $customOptionsData[count($customOptionAttrs)][$v->getData('sku')]["title"] = $v->getData('title');
296
+ $customOptionsData[count($customOptionAttrs)][$v->getData('sku')]["price"] = $v->getData('price');
297
+ $customOptionsData[count($customOptionAttrs)][$v->getData('sku')]["price_type"] = $v->getData('price_type');
298
+ }
299
+ } else {
300
+ // Take a copy of the current SKU list
301
+ // append all the combinations
302
+
303
+ $tempSkuList = array();
304
+ foreach ($values as $k => $v) {
305
+
306
+ $tempSkuList[] = $v->getData('sku');
307
+
308
+ $customOptionsData[count($customOptionAttrs)][$v->getData('sku')] = array();
309
+ $customOptionsData[count($customOptionAttrs)][$v->getData('sku')]["title"] = $v->getData('title');
310
+ $customOptionsData[count($customOptionAttrs)][$v->getData('sku')]["price"] = $v->getData('price');
311
+ $customOptionsData[count($customOptionAttrs)][$v->getData('sku')]["price_type"] = $v->getData('price_type');
312
+ }
313
+
314
+ $newSkuList = array();
315
+
316
+ foreach ($skuList as $oldSku) {
317
+
318
+ foreach ($tempSkuList as $newSku) {
319
+
320
+ $newSkuList[] = $oldSku . "-" . $newSku;
321
+ }
322
+ }
323
+
324
+ $skuList = $newSkuList;
325
+ }
326
+ }
327
+ }
328
+
329
+ // Build up the SKU combinations for each combination of options
330
+ foreach ($skuList as $relsku) {
331
+
332
+ $productXml .= " <SKU><![CDATA[{$relsku}]]></SKU>\n";
333
+ }
334
+ }
335
+
336
+ $variationXml .= " </Variations>\n";
337
+ $productXml .= " </RelatedSKUs>\n";
338
+ $productXml .= $variationXml;
339
+
340
+ $productXml .= " <Custom>\n";
341
+
342
+ // Enumerate all other attribute values
343
+ $productXml .= $this->enumerateCustomAttributesForProduct($product);
344
+
345
+ $productXml .= " </Custom>\n";
346
+ $productXml .= "</Product>\n";
347
+
348
+ // ============ Now generate product elements for all possible custom options ============
349
+ $idIncrement = 1000000;
350
+
351
+ if ($bNeedCustomOptionProducts) {
352
+
353
+ foreach ($skuList as $customSku) {
354
+
355
+ $skuParts = explode("-", str_replace($product->getData('sku'), "temp", $customSku));
356
+
357
+ $productXml .= "<Product>\n";
358
+ $productXml .= " <RemoteId>" . (($idIncrement++) + $product->getId()) . "</RemoteId>\n";
359
+ $productXml .= " <ProductType><![CDATA[" . $attributeSetName . " ]]></ProductType>\n";
360
+ $productXml .= " <Title><![CDATA[{$product->getData('name')} ]]></Title>\n";
361
+ $productXml .= " <Description><![CDATA[{$product->getData('description')} ]]></Description>\n";
362
+ $productXml .= " <SKU><![CDATA[{$customSku}]]></SKU>\n";
363
+ $productXml .= " <Quantity>{$qty}</Quantity>\n";
364
+ $productXml .= " <Category>{$catids}</Category>\n";
365
+ $productXml .= " <CategoryName><![CDATA[{$catnames} ]]></CategoryName>\n";
366
+ $productXml .= " <Image><![CDATA[{$imageUrl}]]></Image>\n";
367
+ $productXml .= " <RelatedSKUs> </RelatedSKUs> <Variations> </Variations>\n";
368
+ $productXml .= " <Custom>\n";
369
+
370
+ // Enumerate all other attribute values
371
+ $productXml .= $this->enumerateCustomAttributesForProduct($product);
372
+
373
+ $basePrice = $product->getData('price');
374
+ $extraPrice = 0.00;
375
+
376
+ $indexTemp = 1;
377
+ for (; $indexTemp < count($skuParts);) {
378
+ $part = $skuParts[$indexTemp];
379
+
380
+ $keycust = $customOptionAttrs[$indexTemp - 1];
381
+
382
+ $custValue = $customOptionsData[$indexTemp][$part]['title'];
383
+
384
+ $priceExtra = $customOptionsData[$indexTemp][$part]['price'];
385
+ $priceType = $customOptionsData[$indexTemp][$part]['price_type'];
386
+
387
+ if ($priceType == "fixed") {
388
+
389
+ $extraPrice += (double) $priceExtra;
390
+ } else if ($priceType == "percent") {
391
+
392
+ $extraPrice += $basePrice * (100.0 + $priceExtra) / 100.0;
393
+ }
394
+
395
+ $productXml .= " <$keycust><![CDATA[" . $custValue . "]]></$keycust>\n";
396
+
397
+ $indexTemp++;
398
+ }
399
+
400
+ $basePrice += $extraPrice; // custom options have prices attached
401
+
402
+ $productXml .= " </Custom>\n";
403
+
404
+
405
+ $productXml .= " <Price>$basePrice</Price>\n";
406
+
407
+ $productXml .= "</Product>\n";
408
+ }
409
+ }
410
+ // =======================================================================================
411
+
412
  unset($product);
 
 
413
  }
414
+
415
+
416
+ return $productXml;
417
+ }
418
+
419
+ public function enumerateCustomAttributesForProduct($product)
420
+ {
421
+ $productXml = "";
422
+
423
+ $attributeNames = array_keys($product->getData());
424
+
425
+ foreach ($attributeNames as $k => $attr) {
426
+
427
+ if (!in_array($attr, array(
428
+ 'name', 'description', 'sku', 'price', 'qty',
429
+ 'stock_item', 'tier_price'
430
+ ))) {
431
+
432
+ if ($attribute = $product->getResource()->getAttribute($attr)) {
433
+
434
+ $myval = $product->getData($attr);
435
+
436
+ if (is_array($myval)) {
437
+ $myval = serialize($myval);
438
+ }
439
+
440
+ if (is_object($attribute) && $attribute->usesSource()) {
441
+
442
+ $prodDataValue = $attribute->getSource()
443
+ ->getOptionText($myval);
444
+
445
+ if ($prodDataValue == '') {
446
+
447
  $prodDataValue = $myval;
448
  }
 
 
449
  }
450
+ else {
451
+ $prodDataValue = $myval;
 
 
 
 
452
  }
453
+
454
+ } else {
455
+ $prodDataValue = $product->getData($attr);
456
+ }
457
+
458
+ if (is_object($prodDataValue)) {
459
+ if ('Varien_Object' == get_class($prodDataValue)) {
460
+
461
+ $prodDataValue = $prodDataValue->toXml();
462
  }
463
+ }
464
+ if (is_array($prodDataValue)) {
465
+
466
+ $prodDataValue = $product->getData($attr);
467
+
468
+ $prodDataValue = str_replace("<![CDATA[", "", $prodDataValue);
469
+ $prodDataValue = str_replace("]]>", "", $prodDataValue);
470
+
471
+ $productXml .= " <$attr><![CDATA[$prodDataValue]]></$attr>\n";
472
+ } else {
473
+
474
+ if (!is_object($prodDataValue)) {
475
+
476
+ $prodDataValue = str_replace("<![CDATA[", "", $prodDataValue);
477
+ $prodDataValue = str_replace("]]>", "", $prodDataValue);
478
+ $productXml .= " <$attr><![CDATA[" . $prodDataValue . "]]></$attr>\n";
479
+ } else if ('Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Type_Configurable_Attribute_Collection'
480
+ == get_class($prodDataValue)) {
481
+ $productXml .= " <$attr><![CDATA[Mage_Core_Model_Mysql4_Collection_Abstract]]></$attr>\n";
482
  }
483
  }
484
  }
 
 
 
 
 
485
  }
486
+ return $productXml;
487
+ }
488
+
489
+ public function generateCuXmlSku($args)
490
+ {
491
+ $row = $args['row'];
492
+ $productId = $row["sku"];
493
+
494
+ echo "<SKU><![CDATA[ " . $productId . " ]]></SKU>";
495
+ }
496
+
497
+ public function generateCuXmlForProductEcho($args)
498
+ {
499
+ echo $this->generateCuXmlForProduct($args);
500
+ }
501
+
502
+ public function generateCuXmlForProduct($args)
503
+ {
504
+ $productXml = '';
505
+ $this->countCurr++;
506
+
507
+ $this->maxMemory = $this->return_bytes(ini_get('memory_limit'));
508
+
509
+ if ($this->runtime < $this->maxruntime
510
  && (memory_get_peak_usage() + $this->changeMemory) < $this->maxMemory
511
+ && $this->countCurr <= $this->upperLimit) {
512
+ $row = $args['row'];
513
+ $this->rangeNext = $row["entity_id"] + 1;
514
+
515
+ $productXml .= $this->generateCuXmlForSingleProduct($row["entity_id"], $args["storeId"]);
516
+
517
+ // after....
518
+ $this->endtime = $this->microtime_float();
519
+ $this->runtime = round($this->endtime - $this->starttime);
520
+
521
+ $tmpval = memory_get_peak_usage() - $this->beforeMemory;
522
+ if ($tmpval > $this->changeMemory) {
523
+ $this->changeMemory = $tmpval;
 
 
 
 
 
 
 
524
  }
525
+ } else {
526
+
527
+ $this->premExit = true; // i.e. exited before got through all prods
 
 
 
 
 
528
  }
529
+
530
+ return $productXml;
531
+ }
532
+
533
+ public function microtime_float()
534
+ {
535
+ list ($msec, $sec) = explode(' ', microtime());
536
+ $microtime = (float) $msec + (float) $sec;
537
+ return $microtime;
538
+ }
539
+
540
+ function return_bytes($val)
541
+ {
542
+ $val = trim($val);
543
+ $last = strtolower($val[strlen($val) - 1]);
544
+ switch ($last) {
545
+ // The 'G' modifier is available since PHP 5.1.0
546
+ case 'g':
547
+ $val *= 1024;
548
+ case 'm':
549
+ $val *= 1024;
550
+ case 'k':
551
+ $val *= 1024;
552
  }
553
+
554
+ return $val;
555
+ }
556
+
557
+ public function doSetValue($request)
558
+ {
559
+ $storeId = (string) $request->StoreviewId;
560
+ $fieldName = (string) $request->FieldName;
561
+ $fieldValue = (string) $request->FieldValue;
562
+ $sku = (string) $request->SKU;
563
+
564
+ $collectionOfProduct = Mage::getModel($this->_collection)->getCollection()->addStoreFilter($storeId);
565
+ $collectionOfProduct->setPageSize(1);
566
+ $collectionOfProduct->setCurPage(1);
567
+ $collectionOfProduct->addFieldToFilter('sku', $sku);
568
+ $product = $collectionOfProduct->getFirstItem();
569
+
570
+ // set an attribute for the product
571
+ $product->setData($fieldName, $fieldValue);
572
+ $product->save();
573
+ }
574
+
575
+ public function getAllSKUs($request)
576
+ {
577
+ $collectionOfProduct = Mage::getModel('catalog/product')->getCollection();
578
+
579
+ $ignoreDisabled = Mage::getStoreConfig('channelunityint/generalsettings/ignoredisabledproducts');
580
+
581
+ if($ignoreDisabled == 1) {
582
+ $collectionOfProduct->addFieldToFilter('status', 1);
583
+ }
584
+
585
+ $sql = $collectionOfProduct->getSelect();
586
+
587
+ Mage::getSingleton('core/resource_iterator')->walk(
588
+ $sql, array(array($this, 'generateCuXmlSku')), array('storeId' => 0), $collectionOfProduct->getSelect()->getAdapter());
589
+ }
590
+
591
+ /**
592
+ * Return a set of product data to CU.
593
+ */
594
+ public function doRead($request)
595
+ {
596
+ $rangeFrom = (string) $request->RangeFrom;
597
+ $rangeTo = (string) $request->RangeTo;
598
+ $storeId = (string) $request->StoreviewId;
599
+
600
+ $this->starttime = $this->microtime_float();
601
+ $this->endtime = $this->microtime_float();
602
+ $this->runtime = round($this->endtime - $this->starttime);
603
+ $this->beforeMemory = memory_get_peak_usage();
604
+ $this->maxMemory = ini_get('memory_limit');
605
+ $this->maxMemoryChar = substr($this->maxMemory, strlen($this->maxMemory) - 1, 1);
606
+
607
+ echo "<Products>\n";
608
+
609
+ try {
610
+
611
+ // get the highest product ID
612
+ if (version_compare(Mage::getVersion(), "1.6.0.0", ">=")
613
+ && class_exists("Mage_Catalog_Model_Resource_Product_Collection")) {
614
+ $collectionOfProduct = Mage::getModel('channelunity/collection')->addStoreFilter($storeId);
615
+ } else {
616
+ $collectionOfProduct = Mage::getModel('catalog/product')->getCollection()->addStoreFilter($storeId);
617
+ }
618
+ $collectionOfProduct->setOrder('entity_id', 'DESC');
619
  $collectionOfProduct->setPageSize(1);
620
  $collectionOfProduct->setCurPage(1);
621
+ $totp = $collectionOfProduct->getFirstItem();
622
+ $totp = $totp->getEntityId();
623
+
624
+ if (version_compare(Mage::getVersion(), "1.6.0.0", ">=")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
625
  && class_exists("Mage_Catalog_Model_Resource_Product_Collection")) {
626
+ $collectionOfProduct = Mage::getModel('channelunity/collection')->addStoreFilter($storeId);
627
+ } else {
628
+ $collectionOfProduct = Mage::getModel('catalog/product')->getCollection()->addStoreFilter($storeId);
629
+ }
630
+
631
+ if($this->ignoreDisabled()) {
632
+ $collectionOfProduct->addFieldToFilter('status', 1);
633
+ }
634
+
635
+ $totalNumProducts = $this->executeQueryScalar(str_replace("SELECT", "SELECT count(*) as count_cu, ", $collectionOfProduct->getSelect()), 'count_cu');
636
+
637
+
638
+ $collectionOfProduct->addAttributeToFilter("entity_id", array('gteq' => $rangeFrom))
639
  ->setOrder('entity_id', 'ASC');
640
+
641
+ // monitor memory and max exec
642
+ if ($this->maxMemoryChar == "M") {
643
+ $this->maxMemory = str_replace("M", "", $this->maxMemory);
644
+ $this->maxMemory = $this->maxMemory * 1024 * 1024;
645
+ } else if ($this->maxMemoryChar == "G") {
646
+ $this->maxMemory = str_replace("G", "", $this->maxMemory);
647
+ $this->maxMemory = $this->maxMemory * 1024 * 1024 * 1024;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
648
  }
649
+
650
+ if ($this->maxMemory < 100) {
651
+ $this->maxMemory = 10000000000;
652
  }
653
+
654
+ $query = str_replace("INNER JOIN", "LEFT JOIN", $collectionOfProduct->getSelect());
655
+
656
+ echo "<Query><![CDATA[$query]]></Query>\n";
657
+
658
+ try {
659
+
660
+ Mage::getSingleton('core/resource_iterator')->walk($query, array(array($this, 'generateCuXmlForProductEcho')), array('storeId' => $storeId), $collectionOfProduct->getSelect()->getAdapter());
661
+ } catch (Exception $x1) {
662
+ Mage::getSingleton('core/resource_iterator')->walk($collectionOfProduct->getSelect(), array(array($this, 'generateCuXmlForProductEcho')), array('storeId' => $storeId));
 
 
 
663
  }
664
+
665
+ // Let the cloud know where to start from the next time it calls
666
+ // for product data
667
+
668
+ if ($this->rangeNext <= $totp) {
669
+ echo "<RangeNext>" . $this->rangeNext . "</RangeNext>\n";
670
+ } else {
671
+ // Start from beginning next time
672
+ echo "<RangeNext>0</RangeNext>\n";
673
  }
674
+
675
+ echo "<TotalProducts>$totalNumProducts</TotalProducts>\n";
676
+ } catch (Exception $x) {
677
+ echo "<Error><![CDATA[" . $x->getTraceAsString() . "]]></Error>\n";
678
+ }
679
+ echo "</Products>\n";
680
+ }
681
+
682
+ private function executeQuery($sql)
683
+ {
684
+ $db = Mage::getSingleton("core/resource")->getConnection("core_write");
685
+
686
+ $result = $db->query($sql);
687
+
688
+ $resultArray = array();
689
+
690
+ foreach ($result as $row) {
691
+
692
+ $resultArray[] = $row;
693
  }
694
+
695
+ return $resultArray;
696
  }
697
+
698
+ private function executeQueryScalar($sql, $column)
699
+ {
700
+ $result = $this->executeQuery($sql);
701
+
702
+ foreach ($result as $row) {
703
+ return $row[$column];
704
+ }
705
+ return -1;
706
+ }
707
+
708
+ }
709
+
app/code/community/Camiloo/Channelunity/controllers/ApiController.php CHANGED
@@ -145,6 +145,10 @@ EOD;
145
  Mage::getModel('channelunity/products')->doSetValue($request);
146
  break;
147
 
 
 
 
 
148
  case "ProductData":
149
  error_reporting(E_ALL);
150
  ini_set("display_errors", "On");
145
  Mage::getModel('channelunity/products')->doSetValue($request);
146
  break;
147
 
148
+ case "GetAllSKUs":
149
+ Mage::getModel('channelunity/products')->getAllSKUs($request);
150
+ break;
151
+
152
  case "ProductData":
153
  error_reporting(E_ALL);
154
  ini_set("display_errors", "On");
app/code/community/Camiloo/Channelunity/etc/config.xml CHANGED
@@ -129,7 +129,7 @@
129
  </channelunity>
130
  </observers>
131
  </catalog_product_save_after>
132
- <catalog_controller_product_delete>
133
  <observers>
134
  <channelunity>
135
  <type>model</type>
@@ -137,7 +137,7 @@
137
  <method>productWasDeleted</method>
138
  </channelunity>
139
  </observers>
140
- </catalog_controller_product_delete>
141
  <controller_action_postdispatch>
142
  <observers>
143
 
@@ -228,6 +228,15 @@
228
  </channelunity>
229
  </observers>
230
  </core_config_data_save_after>
 
 
 
 
 
 
 
 
 
231
  </events>
232
  </global>
233
  <default>
@@ -252,4 +261,4 @@
252
  </channelunitypayment>
253
  </payment>
254
  </default>
255
- </config>
129
  </channelunity>
130
  </observers>
131
  </catalog_product_save_after>
132
+ <catalog_product_delete_before>
133
  <observers>
134
  <channelunity>
135
  <type>model</type>
137
  <method>productWasDeleted</method>
138
  </channelunity>
139
  </observers>
140
+ </catalog_product_delete_before>
141
  <controller_action_postdispatch>
142
  <observers>
143
 
228
  </channelunity>
229
  </observers>
230
  </core_config_data_save_after>
231
+ <store_delete>
232
+ <observers>
233
+ <channelunity>
234
+ <type>model</type>
235
+ <class>channelunity/observer</class>
236
+ <method>storeDelete</method>
237
+ </channelunity>
238
+ </observers>
239
+ </store_delete>
240
  </events>
241
  </global>
242
  <default>
261
  </channelunitypayment>
262
  </payment>
263
  </default>
264
+ </config>
app/code/community/Camiloo/Channelunity/etc/system.xml CHANGED
@@ -73,6 +73,15 @@
73
  <show_in_website>0</show_in_website>
74
  <show_in_store>0</show_in_store>
75
  </apikey>
 
 
 
 
 
 
 
 
 
76
  </fields>
77
  </generalsettings>
78
  </groups>
73
  <show_in_website>0</show_in_website>
74
  <show_in_store>0</show_in_store>
75
  </apikey>
76
+ <ignoredisabledproducts>
77
+ <label>Ignore Disabled Products</label>
78
+ <frontend_type>select</frontend_type>
79
+ <source_model>adminhtml/system_config_source_yesno</source_model>
80
+ <sort_order>35</sort_order>
81
+ <show_in_default>1</show_in_default>
82
+ <show_in_website>0</show_in_website>
83
+ <show_in_store>0</show_in_store>
84
+ </ignoredisabledproducts>
85
  </fields>
86
  </generalsettings>
87
  </groups>
app/design/adminhtml/default/default/template/channelunity/configheader.phtml CHANGED
@@ -16,7 +16,7 @@
16
  <h3>ChannelUnity Integration for Magento</h3>
17
  Devised and Developed in Manchester, UK by <a href="http://www.camiloo.co.uk/?ref=cu" target="_blank">Camiloo Limited</a><br />
18
  <?php
19
- $xml = Mage::getModel('channelunity/checkforupdates')->getRemoteXMLFileData("http://my.channelunity.com/versioncheck.php?Version=1.0.0.8");
20
  $html = $xml->DisplayMessage[0];
21
  echo $html;
22
  ?>
16
  <h3>ChannelUnity Integration for Magento</h3>
17
  Devised and Developed in Manchester, UK by <a href="http://www.camiloo.co.uk/?ref=cu" target="_blank">Camiloo Limited</a><br />
18
  <?php
19
+ $xml = Mage::getModel('channelunity/checkforupdates')->getRemoteXMLFileData("http://my.channelunity.com/versioncheck.php?Version=1.0.0.9");
20
  $html = $xml->DisplayMessage[0];
21
  echo $html;
22
  ?>
package.xml CHANGED
@@ -1,7 +1,7 @@
1
  <?xml version="1.0"?>
2
  <package>
3
  <name>Camiloo_Channelunity</name>
4
- <version>1.0.0.8</version>
5
  <stability>stable</stability>
6
  <license uri="http://www.camiloo.co.uk/license.txt">Camiloo EULA</license>
7
  <channel>community</channel>
@@ -11,11 +11,11 @@
11
 
12
  Should you need any help getting started, please email support@channelunity.com</description>
13
  <notes>The ChannelUnity connector kit for Magento.
14
- Allows products with custom options to be uploaded to ChannelUnity. Prevents order import validation errors.</notes>
15
  <authors><author><name>Camiloo Limited</name><user>auto-converted</user><email>hello@camiloo.co.uk</email></author></authors>
16
- <date>2012-07-02</date>
17
- <time>22:09:39</time>
18
- <contents><target name="magedesign"><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="template"><dir name="channelunity"><file name="configheader.phtml" hash="df298d12a6d69f6acdd974742cf91957"/><file name="paymentinfo.phtml" hash="60967f7ab38fe17c879b272eed25f986"/></dir></dir></dir></dir></dir></target><target name="magecommunity"><dir name="Camiloo"><dir name="Channelunity"><dir name="Block"><file name="Configheader.php" hash="6d7de078f04901e94b8b9675bcd9e4ac"/><file name="Paymentform.php" hash="1f3e79556f15a57b9761c3665a103103"/><file name="Paymentinfo.php" hash="6c3c36d92592dd802fb8045dc065d231"/></dir><dir name="controllers"><file name="ApiController.php" hash="3148140b7866c820607b6b08c4ce8a99"/><file name="ApiController.php.old.php" hash="01ff34c2cf5798a82cfc11b19ab6decd"/></dir><dir name="etc"><file name="config.xml" hash="972a911499e3fb5feb873c2164d409c4"/><file name="system.xml" hash="b43f861f8ab3dadca3c122be10790609"/></dir><dir name="Helper"><file name="Data.php" hash="857d7d23882394c33f96e14dece757c2"/></dir><dir name="Model"><file name="Abstract.php" hash="9562198c4f35997f3cc81e35c35819f2"/><file name="Attributes.php" hash="054b33cadc22acda31056e5b4cb8ff56"/><file name="Categories.php" hash="fd3806b220fd579b00bc5ab5fd464170"/><file name="Checkforupdates.php" hash="e2675f59cc61e54ad1a20f76865ce653"/><file name="Collection.php" hash="707e40c83bfc057ab557b5fad21727e5"/><file name="Customrate.php" hash="f6e64e362fa36b3854d8dacfc3e677c2"/><file name="Entity.php" hash="0032a6c24cb75beb2ae073a56c2a1564"/><file name="Observer.php" hash="2d4c49738479b98889e39dc95d8d65e0"/><file name="Ordercreatebackport.php" hash="dd84aa8fc0c4b62022850bfa74bff37f"/><file name="Orders.php" hash="5fae119970401d888973f5afcd7344a4"/><file name="Payment.php" hash="7fe570cf0aaf7c2bcdf1982b6e69caa6"/><file name="Paymentinfo.php" hash="e11658c9fa02420557441f5c8a41f8a0"/><file name="Paymentmethoduk.php" hash="a99409ed4ee5f7e426df4eaf793482d6"/><file name="Products.php" hash="a0f15a0b178de8bafe09de02192b4fb8"/><file name="Stores.php" hash="7f299877f0b62ca9d30a46b333124680"/></dir><dir name="sql"><dir name="channelunity_setup"><file name="install-1.0.0.php" hash="7127fff7219108813aa35dd7596b09d3"/><file name="mysql4-install-0.0.1.php" hash="7ebc892c87b9401bf402a7e1976133e3"/></dir></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="Camiloo_Channelunity.xml" hash="cccfbce64ee176372c5afecb8676fab0"/></dir></target></contents>
19
  <compatible/>
20
  <dependencies/>
21
  </package>
1
  <?xml version="1.0"?>
2
  <package>
3
  <name>Camiloo_Channelunity</name>
4
+ <version>1.0.0.9</version>
5
  <stability>stable</stability>
6
  <license uri="http://www.camiloo.co.uk/license.txt">Camiloo EULA</license>
7
  <channel>community</channel>
11
 
12
  Should you need any help getting started, please email support@channelunity.com</description>
13
  <notes>The ChannelUnity connector kit for Magento.
14
+ Fixes a problem with VAT/Tax on orders imported. Supports ignoring of Disabled products in Magento. Fixes image on product save event. Fixes stock sync from Magento to CU on order placed and invoice paid events.</notes>
15
  <authors><author><name>Camiloo Limited</name><user>auto-converted</user><email>hello@camiloo.co.uk</email></author></authors>
16
+ <date>2012-08-07</date>
17
+ <time>21:49:47</time>
18
+ <contents><target name="magedesign"><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="template"><dir name="channelunity"><file name="configheader.phtml" hash="911da4fa8a8c8072f50760c4b3d1d919"/><file name="paymentinfo.phtml" hash="60967f7ab38fe17c879b272eed25f986"/></dir></dir></dir></dir></dir></target><target name="magecommunity"><dir name="Camiloo"><dir name="Channelunity"><dir name="Block"><file name="Configheader.php" hash="6d7de078f04901e94b8b9675bcd9e4ac"/><file name="Paymentform.php" hash="1f3e79556f15a57b9761c3665a103103"/><file name="Paymentinfo.php" hash="6c3c36d92592dd802fb8045dc065d231"/></dir><dir name="controllers"><file name="ApiController.php" hash="5553081202b7879db849bc01fccf3e71"/><file name="ApiController.php.old.php" hash="01ff34c2cf5798a82cfc11b19ab6decd"/></dir><dir name="etc"><file name="config.xml" hash="16bd184dead6e9f7d0ee0acc217277a0"/><file name="system.xml" hash="00279011256ddeb605c8863f969ab1fb"/></dir><dir name="Helper"><file name="Data.php" hash="857d7d23882394c33f96e14dece757c2"/></dir><dir name="Model"><file name="Abstract.php" hash="473902ebc19354da31f344732d288f27"/><file name="Attributes.php" hash="054b33cadc22acda31056e5b4cb8ff56"/><file name="Categories.php" hash="fd3806b220fd579b00bc5ab5fd464170"/><file name="Checkforupdates.php" hash="e2675f59cc61e54ad1a20f76865ce653"/><file name="Collection.php" hash="707e40c83bfc057ab557b5fad21727e5"/><file name="Customrate.php" hash="f6e64e362fa36b3854d8dacfc3e677c2"/><file name="Entity.php" hash="0032a6c24cb75beb2ae073a56c2a1564"/><file name="Observer.php" hash="2469dac16146de26953b0075db379797"/><file name="Ordercreatebackport.php" hash="dd84aa8fc0c4b62022850bfa74bff37f"/><file name="Orders.php" hash="b2bb6bcf1e30c4351c2dfb71675bdb72"/><file name="Payment.php" hash="7fe570cf0aaf7c2bcdf1982b6e69caa6"/><file name="Paymentinfo.php" hash="e11658c9fa02420557441f5c8a41f8a0"/><file name="Paymentmethoduk.php" hash="a99409ed4ee5f7e426df4eaf793482d6"/><file name="Products.php" hash="06da832275dbfec0982f12b98f1e946e"/><file name="Stores.php" hash="7f299877f0b62ca9d30a46b333124680"/></dir><dir name="sql"><dir name="channelunity_setup"><file name="install-1.0.0.php" hash="7127fff7219108813aa35dd7596b09d3"/><file name="mysql4-install-0.0.1.php" hash="7ebc892c87b9401bf402a7e1976133e3"/></dir></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="Camiloo_Channelunity.xml" hash="cccfbce64ee176372c5afecb8676fab0"/></dir></target></contents>
19
  <compatible/>
20
  <dependencies/>
21
  </package>