ICS_Connector - Version 1.3.1

Version Notes

Version 1.3.1.

Download this release

Release Info

Developer Intuiko
Extension ICS_Connector
Version 1.3.1
Comparing to
See all releases


Version 1.3.1

app/code/local/Intuiko/ConnectedStore/Block/Button.php ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class Intuiko_ConnectedStore_Block_Button extends Mage_Adminhtml_Block_System_Config_Form_Field
3
+ {
4
+
5
+ protected function _getElementHtml(Varien_Data_Form_Element_Abstract $element)
6
+ {
7
+ $this->setElement($element);
8
+
9
+ $url = Mage::getBaseUrl() . "ping/ping";
10
+
11
+ $jsScript = "document.getElementById('intuiko_connectedstore_test_connection').innerHTML = 'Trying to connect to the ICS API...';";
12
+ $jsScript .= "var xmlhttp = new XMLHttpRequest();";
13
+ $jsScript .= "xmlhttp.onreadystatechange = function() {";
14
+ $jsScript .= "if (xmlhttp.readyState == XMLHttpRequest.DONE ) {";
15
+ $jsScript .= "if(xmlhttp.status == 200){";
16
+ $jsScript .= "document.getElementById('intuiko_connectedstore_test_connection').innerHTML = xmlhttp.responseText;";
17
+ $jsScript .= "}else{";
18
+ $jsScript .= "document.getElementById('intuiko_connectedstore_test_connection').innerHTML = 'Connection failed';";
19
+ $jsScript .= "}}};";
20
+ $jsScript .= "xmlhttp.open('GET', '" . $url . "', true);";
21
+ $jsScript .= "xmlhttp.send();";
22
+
23
+
24
+
25
+ $html = $this->getLayout()->createBlock('adminhtml/widget_button')
26
+ ->setType('button')
27
+ ->setClass('scalable')
28
+ ->setLabel('Test Connection')
29
+ ->setOnClick($jsScript)
30
+ ->toHtml();
31
+
32
+ $html .= "<div id='intuiko_connectedstore_test_connection'></div>";
33
+
34
+ return $html;
35
+ }
36
+ }
37
+ ?>
app/code/local/Intuiko/ConnectedStore/Exception.php ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Intuiko_ConnectedStore_Exception extends Zend_Exception {
4
+ public $codeError;
5
+
6
+ public function __construct($msg = '', $codeError = 0) {
7
+ ICSLogger::error($msg);
8
+ $this->codeError = $codeError;
9
+ parent::__construct($msg, 0, null);
10
+ }
11
+ }
app/code/local/Intuiko/ConnectedStore/Helper/ICSHelper.php ADDED
@@ -0,0 +1,507 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Magento
4
+ */
5
+
6
+ /**
7
+ *
8
+ * Helper class to uses to request Api ICS
9
+ * Example:
10
+ * http://support.qualityunit.com/061754-How-to-make-REST-calls-in-PHP
11
+ *
12
+ */
13
+ class Intuiko_ConnectedStore_Helper_ICSHelper extends Mage_Core_Helper_Abstract {
14
+
15
+ private static $ICS_Error = 'ICS_Error';
16
+ private static $CURLE_OPERATION_TIMEDOUT = '28';
17
+
18
+ private static $API_VERSION = "1.3" ;
19
+
20
+ /** ICS connector status */
21
+ private $status = NULL;
22
+
23
+ /** ICS api url */
24
+ private $uri = NULL;
25
+
26
+ /** Application api key */
27
+ private $apikey = NULL;
28
+
29
+ /** Tenant id */
30
+ private $tenantId = NULL;
31
+
32
+ /** Brand Id */
33
+ private $brandId = NULL;
34
+
35
+ /** Bag Merge Method */
36
+ private $mergeMethod = NULL;
37
+
38
+ /** Time of timeout */
39
+ private $timeout = NULL;
40
+
41
+ /**
42
+ * Init param to call api ICS
43
+ */
44
+ public function Intuiko_ConnectedStore_Helper_ICSHelper(){
45
+ $this->status = Mage::getStoreConfig('connectedstore_section/connectedstore_group/status_field');
46
+ $this->uri = Mage::getStoreConfig('connectedstore_section/connectedstore_group/urlservice_field');
47
+ $this->apikey = Mage::getStoreConfig('connectedstore_section/connectedstore_group/apikey_field');
48
+ $this->tenantId = Mage::getStoreConfig('connectedstore_section/connectedstore_group/tenantid_field');
49
+ $this->brandId = Mage::getStoreConfig('connectedstore_section/connectedstore_group/brandid_field');
50
+ $this->mergeMethod = Mage::getStoreConfig('connectedstore_section/connectedstore_group/mergemethod_field');
51
+ $this->timeout = Mage::getStoreConfig('connectedstore_section/connectedstore_group/timeout_field');
52
+
53
+ if($this->status && (empty($this->uri) || empty($this->apikey) || empty($this->tenantId) || empty($this->brandId))) {
54
+ ICSLogger::error('A field is missing in the configuration, ICS connector will be deactivated.');
55
+ $this->status = false;
56
+ }
57
+ }
58
+
59
+ /**
60
+ * Set the flag value of mode timeout in the session
61
+ *
62
+ * @param Boolean $value The boolean to set in the session
63
+ */
64
+ public static function setIcsFlagError($value){
65
+ $session = Mage::getSingleton('core/session');
66
+ $session->setData(self::$ICS_Error, $value);
67
+ }
68
+
69
+ /**
70
+ * Get the flag value of mode timeout from the session
71
+ *
72
+ * @return Boolean The flag value
73
+ */
74
+ public static function getIcsFlagError(){
75
+ $session = Mage::getSingleton('core/session');
76
+ return $session->getData(self::$ICS_Error);
77
+ }
78
+
79
+
80
+ /**
81
+ * Generate authentication key as followed:
82
+ * 'ICS ' . sha256($salt . $apiKey)
83
+ * where $salt is a timestamp.
84
+ *
85
+ * @param Integer $time The timestamp used as salt
86
+ * @return String The generated authentication key
87
+ */
88
+ private function getKey($time){
89
+ return "ICS " . hash('sha256', $time . $this->apikey);
90
+ }
91
+
92
+ /**
93
+ * Generate header to build a http request on Api ICS
94
+ *
95
+ * @return Array The array of headers used for ICS api request
96
+ */
97
+
98
+ private function getHeader(){
99
+ $date = new DateTime();
100
+ $key = $this->getKey($date->getTimestamp());
101
+
102
+ if($key == NULL){
103
+ return NULL;
104
+ }
105
+ return array(
106
+ 'x-timestamp: '. $date->getTimestamp(),
107
+ 'Authorization: '. $key,
108
+ 'Content-type: application/json; version=' . self::$API_VERSION . '; charset=utf-8',
109
+ 'Accept: application/json; version=' . self::$API_VERSION . '; charset=utf-8'
110
+ ) ;
111
+ }
112
+
113
+ /**
114
+ * Check if the ICS module is in timeout mode.
115
+ *
116
+ * @return bool True if the module is enabled, false otherwise
117
+ */
118
+ public function isICSModuleEnabled() {
119
+ return $this->status && !$this->getIcsFlagError();
120
+ }
121
+
122
+ /**
123
+ * Check if the ICS module is enabled
124
+ *
125
+ * @return bool True if the module is enabled, false otherwise
126
+ */
127
+ public function isIcsModuleStatusEnabled() {
128
+ return $this->status;
129
+ }
130
+
131
+ /**
132
+ * This function does a ping to initialize the communication
133
+ *
134
+ * @return String A pong class response which contains these attributes : tenantName, applicationProfile, active, apiVersion
135
+ */
136
+ public function ping(){
137
+ $header = $this->getHeader();
138
+
139
+ if($header == NULL){
140
+ return NULL;
141
+ }
142
+
143
+ $opts = array('http' => array('method'=>'GET', 'header'=> $header));
144
+ $context = stream_context_create($opts);
145
+
146
+ $time = microtime(true);
147
+
148
+ $pong = json_decode(file_get_contents( $this->uri . 'tenants/' . $this->tenantId . '/brands/' . $this->brandId . '/ping', false, $context));
149
+
150
+ $timeElapsed = microtime(true) - $time;
151
+
152
+ if($pong == false){
153
+ return NULL;
154
+ }
155
+
156
+ $pong->timeElapsed = round($timeElapsed * 1000);
157
+
158
+ return $pong;
159
+ }
160
+
161
+ /**
162
+ * Call the save method of ICS api to save the given bag.
163
+ *
164
+ * @param Bag $bag The bag to be saved in ICS.
165
+ * @return Array|False The api response as an array, or false if an error occurred
166
+ */
167
+ public function save($bag) {
168
+ if(empty($bag)) {
169
+ return false;
170
+ }
171
+
172
+ $path = 'tenants/' . $this->tenantId . '/brands/' . $this->brandId . '/bags';
173
+ try {
174
+ $response = $this->post($bag, $path);
175
+ } catch(Intuiko_ConnectedStore_Exception $e) {
176
+ return false;
177
+ }
178
+
179
+ return json_decode($response, true);
180
+ }
181
+
182
+ /**
183
+ * Call the save method of ICS api to save the given customer.
184
+ *
185
+ * @param Customer $customer The customer to be saved in ICS.
186
+ * @return True|False True if everything is OK, or false if an error occurred
187
+ */
188
+ public function saveCustomer($customer) {
189
+ if(empty($customer)) {
190
+ return false;
191
+ }
192
+
193
+ $path = 'tenants/' . $this->tenantId . '/brands/' . $this->brandId . '/customers';
194
+ try {
195
+ $this->post($customer, $path);
196
+ } catch(Intuiko_ConnectedStore_Exception $e) {
197
+ return false;
198
+ }
199
+
200
+ return true;
201
+ }
202
+
203
+ /**
204
+ * Call the search method of ICS api to get ids of the bags matching the given bag type and belonging to the
205
+ * customer defined by the given appCustomerId or email.
206
+ *
207
+ * @param String $type The bag type
208
+ * @param Mixed $appCustomerId The customer business identifier
209
+ * @param String $email The customer email
210
+ * @param String $twitterId The customer twitter id
211
+ * @return Array|False|Int The api response as an array, or an error code/false if an error occurred
212
+ */
213
+ public function searchBagsIds($type, $appCustomerId, $email, $twitterId) {
214
+ if(empty($type) || (empty($appCustomerId) && empty($email) && empty($twitterId))) {
215
+ return false;
216
+ }
217
+
218
+ $searchBagMessage = new SearchBagMessage($type, $appCustomerId, $email, $twitterId);
219
+ $path = 'tenants/' . $this->tenantId . '/brands/' . $this->brandId . '/bags/_search';
220
+ try {
221
+ $response = $this->put($searchBagMessage, $path);
222
+ } catch(Intuiko_ConnectedStore_Exception $e) {
223
+ return !empty($e->codeError) ? $e->codeError : false;
224
+ }
225
+
226
+ return json_decode($response);
227
+ }
228
+
229
+ /**
230
+ * Call the get method of ICS api to get the bag matching the given id.
231
+ * If a timestamp is provided, the bag will be retrieved if and only if it is more recent than the given timestamp.
232
+ *
233
+ * @param String $bagId The id of the bag to retrieve from ICS
234
+ * @param Int $timestamp The timestamp (default value: NULL)
235
+ * @return Array|False|Int The api response as an array or a int (see get($path) method), or false if an error occurred.
236
+ */
237
+ public function getBagById($bagId, $timestamp = NULL) {
238
+ if(empty($bagId)) {
239
+ return false;
240
+ }
241
+
242
+ $path = 'tenants/' . $this->tenantId . '/brands/' . $this->brandId . '/bags/' . $bagId;
243
+ if(!empty($timestamp)) {
244
+ $path = $path . '?timestamp=' . $timestamp;
245
+ }
246
+
247
+ try {
248
+ $response = $this->get($path);
249
+ } catch(Intuiko_ConnectedStore_Exception $e) {
250
+ return false;
251
+ }
252
+
253
+ if(!empty($response) && is_numeric($response)) {
254
+ return $response;
255
+ }
256
+
257
+ return json_decode($response, true);
258
+ }
259
+
260
+ /**
261
+ * Call the merge method of ICS api to merge two bags.
262
+ * All the modifications will be done on the bag matching the masterBagId.
263
+ * See the api documentation for more details on the different possible merge.
264
+ *
265
+ * @param String $masterBagId The id of the bag that will be considered as the master
266
+ * @param String $slaveBagId The id of the bag that will be considered as the slave
267
+ * @return Array|False The api response as an array, or false if an error occurred
268
+ */
269
+ public function merge($masterBagId, $slaveBagId) {
270
+ if(empty($this->mergeMethod) || empty($masterBagId) || empty($slaveBagId)) {
271
+ return false;
272
+ }
273
+
274
+ $mergeMessage = new MergeMessage($masterBagId, $slaveBagId, $this->mergeMethod);
275
+ $path = 'tenants/' . $this->tenantId . '/brands/' . $this->brandId . '/bags/_merge';
276
+ try {
277
+ $response = $this->post($mergeMessage, $path);
278
+ } catch (Intuiko_ConnectedStore_Exception $e) {
279
+ return false;
280
+ }
281
+
282
+ return json_decode($response, true);
283
+ }
284
+
285
+ /**
286
+ * Call the delete method of ICS api to delete the bag matching the given id.
287
+ *
288
+ * @param String $bagId The id of the bag to delete
289
+ */
290
+ public function delete($bagId) {
291
+ if(empty($bagId)) {
292
+ return;
293
+ }
294
+
295
+ $deleteMessage = new DeleteMessage($bagId);
296
+ $path = 'tenants/' . $this->tenantId . '/brands/' . $this->brandId . '/bags/_delete';
297
+ try {
298
+ $this->put($deleteMessage, $path);
299
+ } catch(Intuiko_ConnectedStore_Exception $e) {}
300
+ }
301
+
302
+
303
+ /**
304
+ * Run Exception if Detect that curl is in timeOut
305
+ *
306
+ * @param curl $ch
307
+ * @param time $time
308
+ * @throws Intuiko_ConnectedStore_Exception
309
+ */
310
+ public function checkTimeOut($ch, $time){
311
+ if(curl_errno($ch) == self::$CURLE_OPERATION_TIMEDOUT){
312
+ curl_close($ch);
313
+ $this->setIcsFlagError(true);
314
+ throw new Intuiko_ConnectedStore_Exception('request ended in timeout error after ' . $time . 's');
315
+ }
316
+ }
317
+
318
+ /**
319
+ * return true when status code is in error, otherwise false.
320
+ *
321
+ * @param unknown_type $statusCode
322
+ */
323
+ public function checkStatusError($statusCode){
324
+ if ($statusCode == 0 || $statusCode >= 300) {
325
+ if ($statusCode == 0 || $statusCode >= 500){
326
+ $this->setIcsFlagError(true);
327
+ }
328
+ return true;
329
+ }
330
+ return false;
331
+ }
332
+
333
+ /**
334
+ * Convert an object to JsonObject without its null attributes
335
+ *
336
+ * @param $entity The object to convert
337
+ */
338
+ private function toJsonObjectWithoutNullAttributes($entity) {
339
+ return json_encode(array_filter((array) $entity, 'filterCallback'));
340
+ }
341
+
342
+ /**
343
+ * Sent POST request with the provided path and entity
344
+ *
345
+ * @param Mixed $entity The entity to send in the request body. It will be encoded in JSON.
346
+ * @param String $path The path of the api method. It will be concatenated to the api url.
347
+ * @throws Intuiko_ConnectedStore_Exception If the http request ends with an error
348
+ * @return String The api response
349
+ */
350
+ private function post($entity, $path){
351
+ $header = $this->getHeader();
352
+
353
+ if($header == NULL){
354
+ throw new Intuiko_ConnectedStore_Exception('Header cannot be null.');
355
+ }
356
+
357
+ if($path == NULL){
358
+ throw new Intuiko_ConnectedStore_Exception('Path cannot be null.');
359
+ }
360
+
361
+ $data = $this->toJsonObjectWithoutNullAttributes($entity);
362
+ $url = $this->uri . $path;
363
+
364
+ ICSLogger::debug('Sent POST request with url=[' . $url . '] and data=[' . $data . ']');
365
+
366
+ $ch = curl_init();
367
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
368
+ curl_setopt($ch, CURLOPT_URL, $url);
369
+ curl_setopt($ch, CURLOPT_POST, true);
370
+ curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
371
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
372
+ curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
373
+ curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
374
+ curl_setopt($ch, CURLOPT_FAILONERROR, false);
375
+ curl_setopt($ch, CURLOPT_TIMEOUT_MS, $this->timeout);
376
+
377
+ $result = curl_exec($ch);
378
+ $statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
379
+ $time = curl_getinfo($ch, CURLINFO_TOTAL_TIME);
380
+
381
+ //Controle erreur
382
+ $this->checkTimeOut($ch, $time);
383
+ curl_close($ch);
384
+
385
+ if($this->checkStatusError($statusCode)){
386
+ $error = json_decode($result, true);
387
+ throw new Intuiko_ConnectedStore_Exception(
388
+ 'POST request ended with error=['. $error['httpCode'] .' - '. $error['message'] .'] - url=['. $url .'] and data=['. $data .']' . $time . 's');
389
+ }
390
+
391
+ ICSLogger::debug('POST request ended with statusCode=[' . $statusCode . '] and content=[' . $result . '] in ' . $time . 's');
392
+ return $result;
393
+ }
394
+
395
+ /**
396
+ * Sent PUT request with the provided path and entity
397
+ *
398
+ * @param Mixed $entity The entity to send in the request body. It will be encoded in JSON.
399
+ * @param String $path The path of the api method. It will be concatenated to the api url.
400
+ * @throws Intuiko_ConnectedStore_Exception
401
+ * @return String The response content or null if an error occurred.
402
+ */
403
+ public function put($entity, $path){
404
+ $header = $this->getHeader();
405
+
406
+ if($header == NULL){
407
+ throw new Intuiko_ConnectedStore_Exception('Header cannot be null.');
408
+ }
409
+
410
+ if($path == NULL){
411
+ throw new Intuiko_ConnectedStore_Exception('Path cannot be null.');
412
+ }
413
+
414
+ $data = $this->toJsonObjectWithoutNullAttributes($entity);
415
+ $url = $this->uri . $path;
416
+ ICSLogger::debug('Sent PUT request with url=[' . $url . '] and data=[' . $data . ']');
417
+
418
+ $ch = curl_init();
419
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
420
+ curl_setopt($ch, CURLOPT_URL, $url);
421
+ curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
422
+ curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
423
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
424
+ curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
425
+ curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
426
+ curl_setopt($ch, CURLOPT_FAILONERROR, false);
427
+ curl_setopt($ch, CURLOPT_TIMEOUT_MS, $this->timeout);
428
+
429
+ $result = curl_exec($ch);
430
+ $statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
431
+ $time = curl_getinfo($ch, CURLINFO_TOTAL_TIME);
432
+
433
+
434
+ //Controle erreur
435
+ $this->checkTimeOut($ch, $time);
436
+ curl_close($ch);
437
+
438
+ if($this->checkStatusError($statusCode)){
439
+ $error = json_decode($result, true);
440
+ if($statusCode === 0 || $statusCode === 500) {
441
+ $error['errorCode'] = -500;
442
+ }
443
+ throw new Intuiko_ConnectedStore_Exception(
444
+ 'PUT request ended with error=['. $error['httpCode'] .' - '. $error['message'] .'] - url=['. $url .'] and data=[' . $data . ']' . $time . 's', $error['errorCode']);
445
+ }
446
+
447
+ ICSLogger::debug('PUT request ended with statusCode=[' . $statusCode . '] and content=[' . $result . '] in ' . $time . 's');
448
+
449
+ return $result;
450
+ }
451
+
452
+ /**
453
+ * Sent GET request with the provided path
454
+ *
455
+ * @param String $path The path of the api method. It will be concatenated to the api url.
456
+ * @throws Intuiko_ConnectedStore_Exception
457
+ * @return String The response content or null if an error occurred.
458
+ */
459
+ public function get($path){
460
+
461
+ $header = $this->getHeader();
462
+
463
+ if($header == NULL){
464
+ throw new Intuiko_ConnectedStore_Exception('Header cannot be null.');
465
+ }
466
+
467
+ if($path == NULL){
468
+ throw new Intuiko_ConnectedStore_Exception('Path cannot be null.');
469
+ }
470
+
471
+ $url = $this->uri . $path;
472
+ ICSLogger::debug('Sent GET request with url=[' . $url . ']');
473
+
474
+ $ch = curl_init();
475
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
476
+ curl_setopt($ch, CURLOPT_URL, $url);
477
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
478
+ curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
479
+ curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
480
+ curl_setopt($ch, CURLOPT_FAILONERROR, false);
481
+ curl_setopt($ch, CURLOPT_HEADER, false);
482
+ curl_setopt($ch, CURLOPT_TIMEOUT_MS, $this->timeout);
483
+
484
+ $result = curl_exec($ch);
485
+ $statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
486
+ $time = curl_getinfo($ch, CURLINFO_TOTAL_TIME);
487
+
488
+
489
+ //Controle erreur
490
+ $this->checkTimeOut($ch, $time);
491
+ curl_close($ch);
492
+
493
+ if (!$statusCode === 404 && $this->checkStatusError($statusCode)) {
494
+ $error = json_decode($result, true);
495
+ throw new Intuiko_ConnectedStore_Exception(
496
+ 'GET request ended with error=['. $error['httpCode'] .' - '. $error['message'] .'] - url=['. $url .']' . $time . 's');
497
+ }
498
+
499
+ ICSLogger::debug('GET request ended with statusCode=[' . $statusCode . '] and content=[' . $result . '] in ' . $time . 's');
500
+
501
+ if($statusCode === 404 || $statusCode === 204) {
502
+ return $statusCode;
503
+ }
504
+
505
+ return $result;
506
+ }
507
+ }
app/code/local/Intuiko/ConnectedStore/Helper/ICSTwitterHelper.php ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Magento
4
+ */
5
+
6
+
7
+ /**
8
+ *
9
+ * Helper class to uses with Twitter Connectors for ICS
10
+ *
11
+ */
12
+ class Intuiko_ConnectedStore_Helper_ICSTwitterHelper extends Mage_Core_Helper_Abstract {
13
+
14
+ public function getTwitterId($customer) {
15
+ if (empty($customer)) {
16
+ return null;
17
+ }
18
+
19
+ // override this return statement to return the customer's twitterId
20
+ return null;
21
+ }
22
+ }
app/code/local/Intuiko/ConnectedStore/Logger/ICSLogger.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class ICSLogger {
4
+
5
+ const ERROR = 1;
6
+ const WARN = 2;
7
+ const INFO = 3;
8
+ const DEBUG = 4;
9
+
10
+ const LOG_FILE = 'ics.log';
11
+
12
+ const LOG_LEVEL = self::DEBUG;
13
+
14
+
15
+ public static function error($message) {
16
+ self::log($message, self::ERROR, Zend_Log::ERR);
17
+ }
18
+
19
+
20
+ public static function warn($message) {
21
+ self::log($message, self::WARN, Zend_Log::WARN);
22
+ }
23
+
24
+
25
+ public static function debug($message) {
26
+ self::log($message, self::DEBUG, Zend_Log::DEBUG);
27
+ }
28
+
29
+
30
+ public static function info($message) {
31
+ self::log($message, self::INFO, Zend_Log::INFO);
32
+ }
33
+
34
+ private static function log($message, $level, $zendLevel) {
35
+ if($level <= self::LOG_LEVEL) {
36
+ Mage::log($message, $zendLevel, self::LOG_FILE);
37
+ }
38
+ }
39
+ }
app/code/local/Intuiko/ConnectedStore/Model/Bag.php ADDED
@@ -0,0 +1,670 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ include 'Entities.php';
4
+ include 'Resource/ICSResource.php';
5
+
6
+ class Bag extends Message {
7
+
8
+ private static $ICS_FlagSynchro = 'ICS_FlagSynchro';
9
+ const DOT_REPLACE = '\uff0e';
10
+
11
+ public $bagId = null;
12
+ public $bagType = null;
13
+ public $bagName = null;
14
+ public $bagItems = array();
15
+ public $coupons = null;
16
+ public $totals = null;
17
+ public $paymentMethod = null;
18
+ public $shipmentMethod = null;
19
+ public $refBagOrigin = null;
20
+ public $lastUpdate = null;
21
+
22
+ /**
23
+ * Default constructor
24
+ */
25
+ private function __construct() {}
26
+
27
+ /**
28
+ * Set the flag value in the session
29
+ *
30
+ * @param Boolean $value The boolean to set in the session
31
+ */
32
+ public static function setIcsFlagSynchroInSession($value){
33
+ $session = Mage::getSingleton('core/session');
34
+ $session->setData(self::$ICS_FlagSynchro, $value);
35
+ }
36
+
37
+ /**
38
+ * Get the flag value from the session
39
+ *
40
+ * @return Boolean The flag value
41
+ */
42
+ public static function getIcsFlagSynchroInSession(){
43
+ $session = Mage::getSingleton('core/session');
44
+ return $session->getData(self::$ICS_FlagSynchro);
45
+ }
46
+
47
+ /**
48
+ * Generates a checksum from the current bag information
49
+ *
50
+ * @return String The checksum of the current bag
51
+ */
52
+ public function getCheckSum() {
53
+ $data = array();
54
+ $data['bagId'] = $this->bagId;
55
+ $data['bagType'] = $this->bagType;
56
+ $data['bagName'] = $this->bagName;
57
+ $data['coupons'] = $this->coupons;
58
+ $data['totals'] = $this->totals;
59
+ $data['paymentMethod'] = $this->paymentMethod;
60
+ $data['shipmentMethod'] = $this->shipmentMethod;
61
+
62
+ $bagItemsChecksum = 0;
63
+ if($this->bagItems != null && is_array($this->bagItems)) {
64
+ foreach($this->bagItems as $bagItem){
65
+ $bagItemsChecksum += hexdec(md5(json_encode($bagItem)));
66
+ }
67
+ }
68
+
69
+ $checksum = hexdec(md5(json_encode($data)));
70
+ return $checksum + $bagItemsChecksum;
71
+ }
72
+
73
+ /**
74
+ * Allows to convert an array from a json stream which represents an ics bag
75
+ *
76
+ * @param Object $jsonBag The json object that represents a bag
77
+ */
78
+ protected function createBagFromJsonObject($jsonBag){
79
+ $this->bagId = $jsonBag['id'];
80
+ $this->lastUpdate = $jsonBag['lastUpdate'];
81
+ $this->bagName = $jsonBag['name'];
82
+ $this->bagType = $jsonBag['bagType'];
83
+ $this->customer = $this->createBagCustomer(Mage::getSingleton('customer/session')->getCustomer());
84
+
85
+ $bagItems = array();
86
+ if($jsonBag['bagItems'] != null){
87
+ foreach($jsonBag['bagItems'] as $serial => $bagItem){
88
+ $currentBagItem = new BagItem();
89
+ if(isset($bagItem['comment'])){
90
+ $currentBagItem->comment = $bagItem['comment'];
91
+ }
92
+ if(isset($bagItem['ean'])){
93
+ $currentBagItem->ean = $bagItem['ean'];
94
+ }
95
+ $currentBagItem->qtyToBill = $bagItem['qtyToBill'];
96
+ $currentBagItem->imgUrl = $bagItem['imgUrl'];
97
+ $currentBagItem->label = $bagItem['label'];
98
+ $currentBagItem->language = $bagItem['language'];
99
+ $currentBagItem->orderedQty = $bagItem['orderedQty'];
100
+ $currentBagItem->qtyUnit = $bagItem['qtyUnit'];
101
+ $currentBagItem->qtyToShip = $bagItem['qtyToShip'];
102
+ $currentBagItem->skuRef = $bagItem['skuRef'];
103
+ $currentBagItem->type = $bagItem['type'];
104
+ $currentBagItem->family = $bagItem['family'];
105
+
106
+ $attributes = array();
107
+ if($bagItem['attributes'] != null) {
108
+ foreach($bagItem['attributes'] as $key=>$value){
109
+ $currentAttribute = new Attribute();
110
+ $currentAttribute->value = $value['value'];
111
+ $attributes[$key] = $currentAttribute;
112
+ }
113
+ }
114
+
115
+ $currentBagItem->attributes = $attributes;
116
+
117
+ if($bagItem['price'] != null){
118
+ $currentPrice = $bagItem['price'];
119
+ $price = new Price();
120
+ $price->base = (float) $currentPrice['base'];
121
+ $price->currency = $currentPrice['currency'];
122
+ $price->sale = $currentPrice['sale'] != null ? (float) $currentPrice['sale'] : null;
123
+ $price->sell = (float) $currentPrice['sell'];
124
+ $price->vat = (float) $currentPrice['vat'];
125
+ $price->vatRate = (float) $currentPrice['vatRate'];
126
+ $currentBagItem->price = $price;
127
+ }
128
+
129
+ if(isset($bagItem['rawData'])) {
130
+ $currentRawData = $bagItem['rawData'];
131
+ $rawData = new RawData();
132
+ $rawData->buyRequest = $currentRawData['buyRequest'];
133
+ $rawData->parentSku = $currentRawData['parentSku'];
134
+ $currentBagItem->rawData = $rawData;
135
+ }
136
+
137
+ $bagItems[$serial] = $currentBagItem;
138
+ }
139
+ }
140
+
141
+ $this->bagItems = $bagItems;
142
+ $this->coupons = $jsonBag['coupons'];
143
+
144
+ $totals = new Totals();
145
+
146
+ if($jsonBag['totals'] != null){
147
+ $bagTotals = $jsonBag['totals'];
148
+
149
+ $totals->currency = $bagTotals['currency'];
150
+ $totals->discount = $bagTotals['discount'];
151
+ $totals->shipping= $bagTotals['shipping'];
152
+ $totals->total = $bagTotals['total'];
153
+ $totals->vat = $bagTotals['vat'];
154
+ $totals->vatRate = $bagTotals['vatRate'];
155
+ $totals->subtotal = $bagTotals['subtotal'];
156
+
157
+ $this->totals = $totals;
158
+ }
159
+
160
+ $this->paymentMethod = $jsonBag['paymentMethod'];
161
+ $this->shipmentMethod = $jsonBag['shipmentMethod'];
162
+ }
163
+
164
+ /**
165
+ * Get ICS geolocalisation from gps.
166
+ *
167
+ * @param String $gps The String containing the latitude and longitude information
168
+ * @return Geoloc The ICS geoloc built from latitude and longitude information
169
+ */
170
+ private function getGeoloc($gps){
171
+ $geoloc = new Geoloc();
172
+ list($lat, $lng) = explode('::', $gps);
173
+ $geoloc->lat = $lat;
174
+ $geoloc->lng = $lng;
175
+
176
+ return $geoloc;
177
+ }
178
+
179
+ /**
180
+ * Get ICS referer from server information.
181
+ *
182
+ * @return Referer The ICS referer built from server information
183
+ */
184
+ private function getReferer(){
185
+ $referer = new Referer();
186
+ $referer->name = $_SERVER['HTTP_REFERER'];
187
+ return $referer;
188
+ }
189
+
190
+ /**
191
+ * Get an ICS context from the magento core session.
192
+ *
193
+ * @param Mage_Core_Model_Session $session
194
+ * @return Context The ICS context built from the session
195
+ */
196
+ protected function getContext($session){
197
+ $context = new Context();
198
+ $context->device = $session->getData("_session_validator_data/http_user_agent");
199
+ $context->ipAddress = $_SERVER['REMOTE_ADDR'];
200
+ $context->referer = $this->getReferer();
201
+
202
+ if (isset($_COOKIE['gps'])) {
203
+ $gps = $_COOKIE["gps"];
204
+ if($gps != NULL){
205
+ $context->geoloc = $this->getGeoloc($gps);
206
+ }
207
+ }
208
+ return $context;
209
+ }
210
+
211
+ /**
212
+ * Get an ICS price from a magento's product.
213
+ *
214
+ * @param Mage_Catalog_Model_Product $product The magento's product
215
+ * @return Price The ICS price built from a product
216
+ */
217
+ protected function getPriceIcs($product) {
218
+ $price = new Price();
219
+ if($product->getPrice() != null) {
220
+ $price->base = (float) $product->getPrice();
221
+ } else {
222
+ $price->base = (float) $product->getFinalPrice();
223
+ }
224
+
225
+ // $price->sale = 0; // FIXME
226
+ $price->sell = (float) $product->getFinalPrice();
227
+ $price->vat = (float) 2.1; // FIXME
228
+ $price->vatRate = (float) 20; // FIXME
229
+ $price->currency = Mage::getStoreConfig(Mage_Directory_Model_Currency::XML_PATH_CURRENCY_BASE);
230
+ return $price;
231
+ }
232
+
233
+ /**
234
+ * Gets the selections id array from bundle options
235
+ *
236
+ * @param Array $bundleOptions The array of bundle options
237
+ * @return Array The array of selections id built from the bundle options
238
+ */
239
+ private function getBundleSelectionIdsFromBundleOptions($bundleOptions) {
240
+ $selectionIds = array();
241
+ foreach($bundleOptions as $selectionId) {
242
+ if(!is_array($selectionId)) {
243
+ array_push($selectionIds, $selectionId);
244
+ } else {
245
+ foreach($selectionId as $selectId) {
246
+ array_push($selectionIds, $selectId);
247
+ }
248
+ }
249
+ }
250
+
251
+ return $selectionIds;
252
+ }
253
+
254
+ /**
255
+ * Get ics attributes from super attributes from buyRequest
256
+ *
257
+ * @param Array $buyRequest The buy request of an item
258
+ * @return Array An array of ICS attributes built from super attributes
259
+ */
260
+ protected function getIcsAttributesFromSuperAttributes($buyRequest) {
261
+ $attributes = array();
262
+
263
+ if(isset($buyRequest['super_attribute'])) {
264
+ $superAttributes = $buyRequest['super_attribute'];
265
+ foreach($superAttributes as $attributeId => $valueId) {
266
+ $attribute = $this->getAttributeByIdOrCode($attributeId);
267
+
268
+ $bagAttribute = new Attribute();
269
+ $bagAttribute->value = $attribute->getSource()->getOptionText($valueId);
270
+ $attributes[$attribute->getData('attribute_code')] = $bagAttribute;
271
+ }
272
+ }
273
+
274
+ return $attributes;
275
+ }
276
+
277
+ /**
278
+ * Get ics bagItems from bundle options from buyRequest
279
+ *
280
+ * @param Array $buyRequest The buy request of an item
281
+ * @return BagItem The ICS item built from bundle options
282
+ */
283
+ protected function getIcsItemsFromBundleOptions($buyRequest) {
284
+ $storeId = Mage::app()->getStore()->getId();
285
+ $bagItems = array();
286
+
287
+ if(isset($buyRequest['bundle_option'])) {
288
+ $selectionIds = $this->getBundleSelectionIdsFromBundleOptions($buyRequest['bundle_option']);
289
+
290
+ foreach($selectionIds as $selectionId) {
291
+ $selection = ICSResource::getSelectionById($selectionId);
292
+ $productId = $selection['product_id'];
293
+ $product = Mage::helper('catalog/product')->getProduct($productId, $storeId, 'productId');
294
+
295
+ if(!is_null($product)) {
296
+ $options = $product->getTypeInstance(true)->getOrderOptions($product);
297
+ $bagItems[$product->getSku()] = $this->getIcsItemFromProduct($product, $options['info_buyRequest'], $selection['selection_qty']);
298
+ }
299
+ }
300
+ }
301
+
302
+ return $bagItems;
303
+ }
304
+
305
+ /**
306
+ * Get ics bagItems from super group from buyRequest
307
+ *
308
+ * @param Array $buyRequest The buy request of an item
309
+ * @return BagItem The ICS item built from super group
310
+ */
311
+ protected function getIcsItemsFromSuperGroup($buyRequest) {
312
+ $storeId = Mage::app()->getStore()->getId();
313
+ $bagItems = array();
314
+
315
+ if(isset($buyRequest['super_group'])) {
316
+ $superGroup = $buyRequest['super_group'];
317
+
318
+ foreach($superGroup as $productId => $qty) {
319
+ $product = Mage::helper('catalog/product')->getProduct($productId, $storeId, 'productId');
320
+
321
+ if($product != null) {
322
+ $options = $product->getTypeInstance(true)->getOrderOptions($product);
323
+ $bagItems[$product->getSku()] = $this->getIcsItemFromProduct($product, $options['info_buyRequest'], $qty);
324
+ }
325
+ }
326
+ }
327
+
328
+ return $bagItems;
329
+ }
330
+
331
+ /**
332
+ * Turn a Quote item into an ICS item
333
+ *
334
+ * @param Mage_Wishlist_Model_Item $item The magento's item
335
+ * @return BagItem The ICS item built from magento's one
336
+ */
337
+ private function getIcsItemFromQuoteItem($item) {
338
+ $product = $item->getProduct();
339
+ $options = $product->getTypeInstance(true)->getOrderOptions($product);
340
+ $buyRequest = $options['info_buyRequest'];
341
+
342
+ $bagItem = $this->getIcsItemFromProduct($product, $buyRequest, $item->getData('qty'));
343
+
344
+ if(isset($buyRequest['options']) || isset($buyRequest['bundle_option']) || isset($buyRequest['links'])) {
345
+ $bagItem->rawData->buyRequest = $buyRequest;
346
+ $bagItem->innerItems = $this->getIcsItemsFromBundleOptions($buyRequest);
347
+ }
348
+
349
+ return $bagItem;
350
+ }
351
+
352
+ /**
353
+ * Get an ICS item from a magento's product
354
+ *
355
+ * @param Mage_Catalog_Model_Product $product The magento's product
356
+ * @param $buyRequest Array The buy request of the item represented by the given product
357
+ * @param Integer $qty The quantity of the product (default: 1)
358
+ * @return BagItem The ICS item built from magento's product
359
+ */
360
+ protected function getIcsItemFromProduct($product, $buyRequest, $qty = 1) {
361
+ $bagItem = new BagItem();
362
+ $qty = round($qty, 2);
363
+
364
+ $bagItem = $this->setSkuInICSItemFromProduct($bagItem, $product);
365
+ $bagItem->orderedQty = $qty;
366
+ $bagItem->qtyUnit = "piece";
367
+ $bagItem->label = $product->getName();
368
+ $bagItem->language = Mage::getBlockSingleton('page/html')->getLang();
369
+ $bagItem->type = $product->getTypeId();
370
+ $bagItem->family = Mage::getModel("eav/entity_attribute_set")->load($product->getAttributeSetId())->getAttributeSetName();
371
+ $bagItem->imgUrl = Mage::getModel('catalog/product_media_config')->getMediaUrl($product->getSmallImage());
372
+ $bagItem->attributes = $this->getIcsAttributesFromSuperAttributes($buyRequest);
373
+ $bagItem->price = $this->getPriceIcs($product);
374
+
375
+ return $bagItem;
376
+ }
377
+
378
+ /**
379
+ * Set the sku and the parent sku if needed in an ICS item from a magento product.
380
+ *
381
+ * @param BagItem $bagItem The ICS item to set sku and parent sku
382
+ * @param Mage_Catalog_Model_Product $product The magento product.
383
+ * @return BagItem The modified item
384
+ */
385
+ protected function setSkuInICSItemFromProduct($bagItem, $product) {
386
+ $parentSku = $product->getData('sku');
387
+ $sku = $product->getSku();
388
+
389
+ if($parentSku != $sku && $product->getTypeId() != Mage_Catalog_Model_Product_Type::TYPE_BUNDLE) {
390
+ $bagItem->skuRef = $sku;
391
+ $bagItem->rawData->parentSku = $parentSku;
392
+ } else {
393
+ /* We took the parent sku to avoid dynamic sku (which are stored in the getSku() method of product model) */
394
+ $bagItem->skuRef = $parentSku;
395
+ }
396
+
397
+ return $bagItem;
398
+ }
399
+
400
+ /**
401
+ * Check if all super attributes from buy request are set.
402
+ *
403
+ * @param Array $buyRequest the buyRequest of an item
404
+ * @return Boolean false if all super attributes have a value, true otherwise.
405
+ */
406
+ protected function isAllAttributesSet($buyRequest) {
407
+ if(isset($buyRequest['super_attribute'])) {
408
+ foreach($buyRequest['super_attribute'] as $valueId) {
409
+ if(!isset($valueId) || empty($valueId)) {
410
+ return false;
411
+ }
412
+ }
413
+ }
414
+ return true;
415
+ }
416
+
417
+ /**
418
+ * Create an light ICS customer from a Magento Customer
419
+ *
420
+ * @param Mage_Customer_Model_Customer $customer The customer from Magento
421
+ * @return Customer A light ICS customer built from the magento's one
422
+ */
423
+ protected function createBagCustomer($customer){
424
+ $res = new Customer();
425
+ $res->appCustomerId = $customer->getId();
426
+ $res->email = $customer->getEmail();
427
+ $res->twitterId = Mage::helper('connectedstore/ICSTwitterHelper')->getTwitterId($customer);
428
+ return $res;
429
+ }
430
+
431
+ /**
432
+ *
433
+ * Get guest customer information from quote.
434
+ *
435
+ * @param Mage_Sales_Model_Quote $quote The quote
436
+ * @return Customer The customer in guest mode
437
+ */
438
+ protected function getGuestFromQuote($quote) {
439
+ $res = new Customer();
440
+ $res->appCustomerId = $quote->getData('customer_id');
441
+ $res->firstName = $quote->getData('customer_firstname');
442
+ $res->lastName = $quote->getData('customer_lastname');
443
+ $res->email = $quote->getData('customer_email');
444
+
445
+ $addresses = $quote->getAllAddresses();
446
+ // We get the billing address
447
+ $billingAddress = NULL;
448
+ if($addresses != NULL && count($addresses) == 1) {
449
+ $billingAddress = $addresses[0];
450
+ } else if($addresses != NULL && count($addresses) > 0) {
451
+ for($i=0; $i<count($addresses); $i++) {
452
+ $address = $addresses[$i];
453
+ if($address != null && $address->getData('address_type') != null && $address->getData('address_type') === Mage_Sales_Model_Quote_Address::TYPE_BILLING) {
454
+ $billingAddress = $addresses[$i];
455
+ break;
456
+ }
457
+ }
458
+ }
459
+
460
+ if($billingAddress != NULL) {
461
+ $res->city = $billingAddress->getCity();
462
+ $res->country = $billingAddress->getCountryId();
463
+ $res->zipCode = $billingAddress->getPostcode();
464
+ $res->address = $billingAddress->getData("street");
465
+ }
466
+
467
+ return $res;
468
+ }
469
+
470
+ /**
471
+ * Generate a key for a configurable product
472
+ * The key is generated as followed: sku-attribute1-attribute2-...
473
+ *
474
+ * @param BagItem $bagItem An ICS item
475
+ * @return String A generated key from the attributes of the item
476
+ */
477
+ protected function generateBagItemKeyFromAttributes($bagItem) {
478
+ $sku = $bagItem->skuRef;
479
+ $attributes = $bagItem->attributes;
480
+
481
+ $key = $sku;
482
+ if(isset($attributes)) {
483
+ foreach($attributes as $value) {
484
+ $attributeValue = $value->value;
485
+ if(isset($attributeValue) && !empty($attributeValue)) {
486
+ $key .= '-' . $value->value;
487
+ }
488
+ }
489
+ }
490
+ return str_replace('.', self::DOT_REPLACE, $key);
491
+ }
492
+
493
+ /**
494
+ * Generates a key with a bagItem inner items.
495
+ *
496
+ * @param BagItem $bagItem The item which key needs to be generated
497
+ * @return String The generated key
498
+ */
499
+ protected function generateBagItemKeyFromChildren($bagItem){
500
+ $str = $bagItem->skuRef;
501
+ if(!is_null($bagItem->innerItems)){
502
+ foreach($bagItem->innerItems as $children){
503
+ $qty = round($children->orderedQty, 2);
504
+ $str .= '-' . $qty . '-' . $children->skuRef;
505
+ }
506
+ }
507
+ return str_replace('.', self::DOT_REPLACE, $str);
508
+ }
509
+
510
+ /**
511
+ * Create a cart or an order from a quote
512
+ *
513
+ * @param Mage_Sales_Model_Quote $quote The quote
514
+ */
515
+ protected function constructCartOrOrderFromQuote($quote) {
516
+ $session = Mage::getSingleton('core/session');
517
+
518
+ // We get the customer
519
+ $customerSession = Mage::getSingleton('customer/session')->getCustomer();
520
+ $customer = $this->createBagCustomer($customerSession);
521
+ if($customer != null && $customer->email != null){
522
+ $this->customer = $customer;
523
+ }
524
+
525
+ //set origin
526
+ if(Mage::app()->getRequest()->getModuleName() == 'wishlist' && Mage::app()->getRequest()->getActionName() == 'cart'){
527
+ $this->refBagOrigin = Wishlist::getIcsWishlistIdInSession();
528
+ }
529
+
530
+ $context = $this->getContext($session);
531
+ $this->context = $context;
532
+
533
+ // We get the bagId in session
534
+ $cartId = $session->getData(Cart::$ICS_CartId);
535
+ if($cartId != NULL) {
536
+ $this->bagId = $cartId;
537
+ }
538
+
539
+ $this->bagItems = array();
540
+ foreach ($quote->getAllVisibleItems() as $item) {
541
+ $icsItem = $this->getIcsItemFromQuoteItem($item);
542
+ if($icsItem->type === 'bundle') {
543
+ $key = $this->generateBagItemKeyFromChildren($icsItem);
544
+ } else {
545
+ $key = str_replace('.', self::DOT_REPLACE, $item->getProduct()->getSku());
546
+ }
547
+
548
+ if(isset($this->bagItems[$key])) {
549
+ $bagItem = $this->bagItems[$key];
550
+ $bagItem->orderedQty += $icsItem->orderedQty;
551
+ $bagItem->qtyToShip += $icsItem->qtyToShip;
552
+ $bagItem->qtyToBill += $icsItem->qtyToBill;
553
+ $this->bagItems[$key] = $bagItem;
554
+ } else {
555
+ $this->bagItems[$key] = $icsItem;
556
+ }
557
+ }
558
+
559
+ if(strlen($quote->getData('coupon_code'))) {
560
+ $this->coupons = array($quote->getData('coupon_code') => 1);
561
+ } else {
562
+ $this->coupons = null;
563
+ }
564
+ }
565
+
566
+ /**
567
+ * Build an array of magento useful attributes to add a product into a cart/wishlist
568
+ *
569
+ * @param BagItem $bagItem The ICS item
570
+ * @return array An array containing all attributes to add a product into a cart/wishlist
571
+ */
572
+ public function getProductDataFromBagItem($bagItem) {
573
+ $productData = array();
574
+
575
+ $rawData = $bagItem->rawData;
576
+ if(isset($rawData) && isset($rawData->buyRequest)) {
577
+ $productData = $rawData->buyRequest;
578
+ $productData['product_id'] = $productData['product'];
579
+ } else {
580
+ $productModel = Mage::getModel('catalog/product');
581
+ $productId = $productModel->getIdBySku($bagItem->skuRef);
582
+
583
+ if(isset($bagItem->attributes) && count($bagItem->attributes) > 0) {
584
+ $product = $productModel->load($productId);
585
+ $superAttributes = array();
586
+ foreach($bagItem->attributes as $key=>$value) {
587
+ $superAttributes[$this->getAttributeIdByCode($key)] = $product->getData($key);
588
+ }
589
+ $productData['super_attribute'] = $superAttributes;
590
+ }
591
+
592
+ $productData['sku'] = isset($rawData->parentSku) ? $rawData->parentSku : $bagItem->skuRef;
593
+ }
594
+
595
+ $productData['qty'] = $bagItem->orderedQty;
596
+
597
+ return $productData;
598
+ }
599
+
600
+ /**
601
+ * Get an attribute code by its id
602
+ *
603
+ * @param Integer $attributeId The attribute id
604
+ * @return String The attribute code matching the given id
605
+ */
606
+ public function getAttributeCodeById($attributeId) {
607
+ return $this->getAttributeByIdOrCode($attributeId)->getData('attribute_code');
608
+ }
609
+
610
+ /**
611
+ * Get an attribute id by its code
612
+ *
613
+ * @param String $attributeCode The attribute code
614
+ * @return Integer The attribute id matching the given code
615
+ */
616
+ public function getAttributeIdByCode($attributeCode) {
617
+ return $this->getAttributeByIdOrCode($attributeCode)->getData('attribute_id');
618
+ }
619
+
620
+ /**
621
+ * Get an attribute by its code or id.
622
+ * The entity type of the attribute is fixed to catalog_product
623
+ *
624
+ * @param Integer|String The code or the id of the attribute to retrieve
625
+ * @return Mage_Eav_Model_Entity_Attribute_Abstract The attribute matching the given id/code
626
+ */
627
+ public function getAttributeByIdOrCode($identifier) {
628
+ $model = Mage::getModel('eav/config');
629
+ $entityType = $model->getEntityType(Mage_Catalog_Model_Product::ENTITY);
630
+ return $model->getAttribute($entityType, $identifier);
631
+ }
632
+
633
+ /**
634
+ * Check some fields and gives them always the same value if they are null or empty.
635
+ * The goal is to avoid a field is empty at a moment and null at another moment.
636
+ *
637
+ * This method does NOT check mandatory fields.
638
+ */
639
+ public function checkFields() {
640
+ // bag items
641
+ if(!is_null($this->bagItems)) {
642
+ foreach($this->bagItems as $key=>$bagItem) {
643
+ $bagItem->checkFields();
644
+ $this->bagItems[$key] = splitNullValuesInObject($bagItem);
645
+ }
646
+ }
647
+
648
+ // totals
649
+ if($this->totals != null) {
650
+ $this->totals = splitNullValuesInObject($this->totals);
651
+ }
652
+
653
+ // context
654
+ if($this->context != null) {
655
+ $this->context->checkFields();
656
+ $this->context = splitNullValuesInObject($this->context);
657
+ }
658
+
659
+ // customer
660
+ if($this->customer != null) {
661
+ $this->customer->checkFields();
662
+ $this->customer = splitNullValuesInObject($this->customer);
663
+ }
664
+ }
665
+ }
666
+
667
+ class Message {
668
+ public $context = null;
669
+ public $customer = null;
670
+ }
app/code/local/Intuiko/ConnectedStore/Model/Cart.php ADDED
@@ -0,0 +1,233 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Cart extends Bag {
4
+
5
+ protected static $ICS_CartId = 'ICS_CartId';
6
+ protected static $ICS_CartChecksum = 'ICS_CartChecksum';
7
+ protected static $ICS_CartLastUpdate = 'ICS_CartLastUpdate';
8
+ /** Name of the ICS type for cart */
9
+ const ICS_TYPE = 'CART';
10
+
11
+
12
+ /**
13
+ * Default constructor.
14
+ */
15
+ public function __construct() {
16
+ $this->checkFields();
17
+ }
18
+
19
+ /**
20
+ * A static function which instanciates a Cart and feeds it with quote information.
21
+ *
22
+ * @param Mage_Sales_Model_Quote $quote The cart's quote
23
+ * @return Cart A new cart built from the quote
24
+ */
25
+ public static function createCart($quote) {
26
+ $cart = new Cart();
27
+ $cart->bagType = self::ICS_TYPE;
28
+ $cart->constructCartOrOrderFromQuote($quote);
29
+ $cart->setTotalsForCart($quote);
30
+ $cart->checkFields();
31
+ return $cart;
32
+ }
33
+
34
+ /**
35
+ * Create a Cart from the given json object.
36
+ *
37
+ * @param Object $jsonObject The json stream that represents a cart
38
+ * @return Cart A cart built from the json stream
39
+ */
40
+ public static function createCartFromJsonObject($jsonObject) {
41
+ $cart = new Cart();
42
+
43
+ if(empty($jsonObject)) {
44
+ return $cart;
45
+ }
46
+
47
+ $cart->createBagFromJsonObject($jsonObject);
48
+ $cart->checkFields();
49
+ return $cart;
50
+ }
51
+
52
+ /**
53
+ * Set the cart's checksum given in parameter in session.
54
+ *
55
+ * @param String $checksum The cart checksum
56
+ */
57
+ public static function setCartChecksumInSession($checksum){
58
+ Mage::getSingleton('core/session')->setData(self::$ICS_CartChecksum, $checksum);
59
+ }
60
+
61
+ /**
62
+ * Get the current cart's checksum in session.
63
+ *
64
+ * @return String The cart checksum
65
+ */
66
+ public static function getCartChecksumInSession(){
67
+ return Mage::getSingleton('core/session')->getData(self::$ICS_CartChecksum);
68
+ }
69
+
70
+ /**
71
+ * Set the Cart id given in parameter in session.
72
+ *
73
+ * @param Integer $cartId The current cartId
74
+ */
75
+ public static function setIcsCartIdInSession($cartId){
76
+ Mage::getSingleton('core/session')->setData(self::$ICS_CartId, $cartId);
77
+ }
78
+
79
+ /**
80
+ * Get the current cart id from the session.
81
+ *
82
+ * @return Integer the current cart id
83
+ */
84
+ public static function getIcsCartIdInSession(){
85
+ return Mage::getSingleton('core/session')->getData(self::$ICS_CartId);
86
+ }
87
+
88
+ /**
89
+ * Set the Cart's date of last update given in parameter in session.
90
+ *
91
+ * @param String $date The date to set in the session
92
+ */
93
+ public static function setCartLastUpdateInSession($date){
94
+ Mage::getSingleton('core/session')->setData(self::$ICS_CartLastUpdate, $date);
95
+ }
96
+
97
+ /**
98
+ * Get the cart's date of last update from session.
99
+ *
100
+ * @return String Cart's date of last update in session
101
+ */
102
+ public static function getCartLastUpdateInSession(){
103
+ return Mage::getSingleton('core/session')->getData(self::$ICS_CartLastUpdate);
104
+ }
105
+
106
+ /**
107
+ * Set the several information in session:
108
+ * -> The given cartId
109
+ * -> The given checksum
110
+ * -> The given lastUpdate
111
+ *
112
+ * @param Integer $cartId The current cartId
113
+ * @param String $checksum The cart checksum
114
+ * @param String $lastUpdate The cart last update
115
+ */
116
+ public static function setIcsInfoInSession($cartId, $checksum, $lastUpdate) {
117
+ self::setIcsCartIdInSession($cartId);
118
+ self::setCartChecksumInSession($checksum);
119
+ self::setCartLastUpdateInSession($lastUpdate);
120
+ }
121
+
122
+ /**
123
+ * Flush all cart information in session
124
+ */
125
+ public static function resetIcsInfoInSession() {
126
+ self::setIcsCartIdInSession(null);
127
+ self::setCartChecksumInSession(null);
128
+ self::setCartLastUpdateInSession(null);
129
+ Mage::helper('connectedstore/ICSHelper')->setIcsFlagError(false);
130
+ }
131
+
132
+ /**
133
+ * Flush the quote of the given customer.
134
+ *
135
+ * @param Mage_Customer_Model_Customer $customer The customer
136
+ */
137
+ public static function flushCustomerQuote($customer){
138
+ if(empty($customer)) {
139
+ return;
140
+ }
141
+
142
+ $quote = Mage::getModel('sales/quote')->loadByCustomer($customer);
143
+ $quote = self::removeAllItems($quote);
144
+ $quote->collectTotals()->save();
145
+ }
146
+
147
+ /**
148
+ * Import the current cart in the quote of the given customer.
149
+ *
150
+ * @param Mage_Customer_Model_Customer $customer The current customer
151
+ */
152
+ public function importIntoMagento($customer) {
153
+ $storeId = Mage::app()->getStore()->getId();
154
+ if(empty($this->bagId) || empty($storeId)) {
155
+ return;
156
+ }
157
+
158
+ self::flushCustomerQuote($customer);
159
+ $quoteId = Mage::getModel('sales/quote')->loadByCustomer($customer)->getId();
160
+
161
+ if(!empty($this->bagItems)) {
162
+ $api = new Mage_Checkout_Model_Cart_Product_Api();
163
+ $productsData = array();
164
+ foreach($this->bagItems as $bagItem) {
165
+ $productData = $this->getProductDataFromBagItem($bagItem);
166
+ $productId = empty($productData['product_id'])
167
+ ? Mage::getModel('catalog/product')->getIdBySku($productData['sku'])
168
+ : $productData['product_id'];
169
+ $productToTest = Mage::getModel('catalog/product')->loadByAttribute('entity_id', $productId);
170
+ $productData['product_id'] = $productId;
171
+ if(!empty($productToTest)) {
172
+ array_push($productsData, $productData);
173
+ }
174
+ }
175
+
176
+ if(!(empty($productsData))) {
177
+ try {
178
+ $api->add($quoteId, $productsData, $storeId);
179
+ } catch (Exception $e) {
180
+ ICSLogger::error('At least one product does not exist in database for bag : ' . $this->bagId);
181
+ }
182
+ }
183
+ }
184
+
185
+ if(!empty($this->coupons) && is_array($this->coupons)){
186
+ $apiCoupon = new Mage_Checkout_Model_Cart_Coupon_Api();
187
+ $keys = array_keys($this->coupons);
188
+ $apiCoupon->add($quoteId, $keys[0], $storeId);
189
+ }
190
+ }
191
+
192
+ /**
193
+ * Set the cart's totals
194
+ *
195
+ * @param Mage_Sales_Model_Quote $quote The cart's quote
196
+ */
197
+ private function setTotalsForCart($quote) {
198
+ $totals = new Totals();
199
+
200
+ $cartTotals = $quote->getTotals();
201
+
202
+ $totals->subtotal = $cartTotals["subtotal"]->getValue();
203
+ $totals->total = $cartTotals["grand_total"]->getValue();
204
+
205
+ if(isset($cartTotals['discount']) && $cartTotals['discount']->getValue()) {
206
+ $totals->discount = $cartTotals['discount']->getValue();
207
+ }
208
+
209
+ if(isset($cartTotals['tax']) && $cartTotals['tax']->getValue()) {
210
+ $totals->vat = $cartTotals['tax']->getValue();
211
+ }
212
+
213
+ $totals->currency = Mage::getStoreConfig(Mage_Directory_Model_Currency::XML_PATH_CURRENCY_BASE);
214
+
215
+ $this->totals = $totals;
216
+ }
217
+
218
+ /**
219
+ * Removes all the items of a quote given in parameter
220
+ *
221
+ * @param Quote $quote A quote to flush
222
+ */
223
+ private static function removeAllItems($quote) {
224
+ foreach ($quote->getItemsCollection() as $itemId => $item) {
225
+ if (is_null($item->getId())) {
226
+ $quote->getItemsCollection()->removeItemByKey($itemId);
227
+ } else {
228
+ $item->isDeleted(true);
229
+ }
230
+ }
231
+ return $quote;
232
+ }
233
+ }
app/code/local/Intuiko/ConnectedStore/Model/Customer.php ADDED
@@ -0,0 +1,129 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Customer {
4
+ protected static $ICS_CustomerChecksum = 'ICS_CustomerChecksum';
5
+
6
+ public $appCustomerId = NULL;
7
+ public $email = NULL;
8
+ public $firstName = NULL;
9
+ public $lastName = NULL;
10
+ public $address = NULL;
11
+ public $zipCode = NULL;
12
+ public $city = NULL;
13
+ public $country = NULL;
14
+ public $loyaltyCards = array();
15
+ public $rawData = NULL;
16
+ public $twitterId = NULL;
17
+
18
+ /**
19
+ * Check some fields and gives them always the same value if they are null or empty.
20
+ * The goal is to avoid a field is empty at a moment and null at another moment.
21
+ *
22
+ * This method does NOT check mandatory fields.
23
+ */
24
+ public function checkFields() {
25
+ // loyalty cards
26
+ if(!is_null($this->loyaltyCards)) {
27
+ foreach($this->loyaltyCards as $key=>$loyaltyCard) {
28
+ $loyaltyCard->checkFields();
29
+ $this->loyaltyCards[$key] = splitNullValuesInObject($loyaltyCard);
30
+ }
31
+ }
32
+
33
+ // rawData
34
+ if($this->rawData != null) {
35
+ $this->rawData = splitNullValuesInObject($this->rawData);
36
+ }
37
+ }
38
+
39
+ /**
40
+ * Create an ICS customer from a Magento Customer
41
+ *
42
+ * @param Mage_Customer_Model_Customer $customer The customer from Magento
43
+ * @return Customer An ICS customer built from the magento's one
44
+ */
45
+ public static function createIcsCustomer($customer){
46
+ $addresses = $customer->getAddressesCollection()->getItems();
47
+
48
+ $res = new Customer();
49
+ $res->appCustomerId = $customer->getId();
50
+ $res->firstName = $customer->getFirstname();
51
+ $res->lastName = $customer->getLastname();
52
+ $res->email = $customer->getEmail();
53
+ $res->twitterId = Mage::helper('connectedstore/ICSTwitterHelper')->getTwitterId($customer);
54
+
55
+ // Array indexes are the addresses' ids
56
+ $keys = array_keys($addresses);
57
+
58
+ $billingAddress = NULL;
59
+ if($addresses != NULL && count($addresses) == 1){
60
+ $billingAddress = $addresses[$keys[0]];
61
+ }else if($addresses != NULL && count($addresses) > 0){
62
+ for($i=0; $i<count($addresses); $i++) {
63
+ $address = $addresses[$keys[$i]];
64
+ if($address->getId() != NULL && $customer->getDefaultBilling() === $address->getId()) {
65
+ $billingAddress = $addresses[$keys[$i]];
66
+ break;
67
+ }
68
+ }
69
+ }
70
+
71
+ if($billingAddress != NULL) {
72
+ $res->city = $billingAddress->getCity();
73
+ $res->country = $billingAddress->getCountryId();
74
+ $res->zipCode = $billingAddress->getPostcode();
75
+ $res->address = $billingAddress->getData("street");
76
+ }
77
+
78
+ return $res;
79
+ }
80
+
81
+ /**
82
+ * Generate a checksum for this
83
+ */
84
+ public function getCheckSum() {
85
+ $data = array();
86
+
87
+ $data['appCustomerId'] = $this->appCustomerId;
88
+ $data['email'] = $this->email;
89
+ $data['firstName'] = $this->firstName;
90
+ $data['lastName'] = $this->lastName;
91
+ $data['address'] = $this->address;
92
+ $data['zipCode'] = $this->zipCode;
93
+ $data['city'] = $this->city;
94
+ $data['country'] = $this->country;
95
+ // TODO : g�rer les cartes de fid
96
+ //$data['loyaltyCards'] = $this->bagType;
97
+ $data['rawData'] = $this->rawData;
98
+ $data['twitterId'] = $this->twitterId;
99
+
100
+ $checksum = hexdec(md5(json_encode($data)));
101
+ return $checksum;
102
+ }
103
+
104
+
105
+ /**
106
+ * Set the checksum of the customer given in parameter in session.
107
+ *
108
+ * @param String $checksum The cart checksum
109
+ */
110
+ public static function setCustomerChecksumInSession($checksum){
111
+ Mage::getSingleton('core/session')->setData(self::$ICS_CustomerChecksum, $checksum);
112
+ }
113
+
114
+ /**
115
+ * Get the current checksum of the customer in session.
116
+ *
117
+ * @return String The cart checksum
118
+ */
119
+ public static function getCustomerChecksumInSession(){
120
+ return Mage::getSingleton('core/session')->getData(self::$ICS_CustomerChecksum);
121
+ }
122
+
123
+ /**
124
+ * Reset the checksum of the customer in session
125
+ */
126
+ public static function resetCustomerChecksumInSession() {
127
+ self::setCustomerChecksumInSession(null);
128
+ }
129
+ }
app/code/local/Intuiko/ConnectedStore/Model/Entities.php ADDED
@@ -0,0 +1,148 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ include 'Customer.php';
4
+
5
+ function filterCallback($var) {
6
+ if(is_object($var)) {
7
+ $tmp = get_object_vars($var);
8
+ return count($tmp) > 0;
9
+ }
10
+ return $var === 0 || !empty($var);
11
+ }
12
+
13
+ /**
14
+ * Delete all null values in an object
15
+ *
16
+ * @param $object
17
+ */
18
+ function splitNullValuesInObject($object) {
19
+ return (object) array_filter((array) $object, 'filterCallback');
20
+ }
21
+
22
+ class Geoloc {
23
+ public $lat = NULL;
24
+ public $lng = NULL;
25
+ }
26
+
27
+ class Referer {
28
+ public $type = NULL;
29
+ public $name = NULL;
30
+ public $campaign = NULL;
31
+ }
32
+
33
+ class Context {
34
+ public $device = NULL;
35
+ public $geoloc = NULL;
36
+ public $refSalesAssociate = NULL;
37
+ public $refShop = NULL;
38
+ public $referer = NULL;
39
+ public $ipAddress = NULL;
40
+ public $checkIn = NULL; // Boolean
41
+
42
+ /**
43
+ * Check some fields and gives them always the same value if they are null or empty.
44
+ * The goal is to avoid a field is empty at a moment and null at another moment.
45
+ *
46
+ * This method does NOT check mandatory fields.
47
+ */
48
+ public function checkFields() {
49
+ // referer
50
+ if($this->referer != null) {
51
+ $this->referer = splitNullValuesInObject($this->referer);
52
+ }
53
+
54
+ // geoloc
55
+ if($this->geoloc != null) {
56
+ $this->geoloc = splitNullValuesInObject($this->geoloc);
57
+ }
58
+ }
59
+ }
60
+
61
+ class LoyaltyCard {
62
+ public $refBrand = NULL;
63
+ public $number = NULL;
64
+ public $rawData = NULL;
65
+
66
+ /**
67
+ * Check some fields and gives them always the same value if they are null or empty.
68
+ * The goal is to avoid a field is empty at a moment and null at another moment.
69
+ *
70
+ * This method does NOT check mandatory fields.
71
+ */
72
+ public function checkFields() {
73
+ // rawData
74
+ if($this->rawData != null) {
75
+ $this->rawData = splitNullValuesInObject($this->rawData);
76
+ }
77
+ }
78
+ }
79
+
80
+ class Attribute {
81
+ public $value = NULL;
82
+ }
83
+
84
+ class Price {
85
+ public $base = NULL;
86
+ public $sale = NULL;
87
+ public $sell = NULL;
88
+ public $vat = NULL;
89
+ public $vatRate = NULL;
90
+ public $currency = NULL;
91
+ }
92
+
93
+ class BagItem {
94
+
95
+ public $ean = NULL;
96
+ public $skuRef = NULL;
97
+ public $orderedQty = NULL;
98
+ public $qtyToBill = NULL;
99
+ public $qtyToShip = NULL;
100
+ public $qtyUnit = NULL;
101
+ public $label = NULL;
102
+ public $language = NULL;
103
+ public $type = NULL;
104
+ public $family = NULL;
105
+ public $imgUrl = NULL;
106
+ public $comment = NULL;
107
+ public $attributes = array();
108
+ public $price = NULL;
109
+ public $rawData = NULL;
110
+ public $innerItems = array();
111
+
112
+ public function __construct() {
113
+ $this->rawData = new RawData();
114
+ }
115
+
116
+ /**
117
+ * Check some fields and gives them always the same value if they are null or empty.
118
+ * The goal is to avoid a field is empty at a moment and null at another moment.
119
+ *
120
+ * This method does NOT check mandatory fields.
121
+ */
122
+ public function checkFields() {
123
+ // price
124
+ if($this->price != null) {
125
+ $this->price = splitNullValuesInObject($this->price);
126
+ }
127
+
128
+ // rawData
129
+ if($this->rawData != null) {
130
+ $this->rawData = splitNullValuesInObject($this->rawData);
131
+ }
132
+ }
133
+ }
134
+
135
+ class RawData {
136
+ public $buyRequest = NULL;
137
+ public $parentSku = NULL;
138
+ }
139
+
140
+ class Totals {
141
+ public $subtotal = NULL;
142
+ public $discount = NULL;
143
+ public $shipping = NULL;
144
+ public $total = NULL;
145
+ public $vat = NULL;
146
+ public $vatRate = NULL;
147
+ public $currency = NULL;
148
+ }
app/code/local/Intuiko/ConnectedStore/Model/MergeMethods.php ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Intuiko_ConnectedStore_Model_MergeMethods
4
+ {
5
+ public function toOptionArray()
6
+ {
7
+ return array(
8
+ array('value'=>'CLASSIC', 'label'=>'Classic'),
9
+ array('value'=>'KEEP_HIGHEST_QUANTITIES', 'label'=>'Keep highest quantities'),
10
+ array('value'=>'KEEP_SLAVE', 'label'=>'Keep slave'),
11
+ array('value'=>'KEEP_MASTER', 'label'=>'Keep master'),
12
+ array('value'=>'EXCLUSIVE_ADD_FROM_SLAVE', 'label'=>'Exclusive add from slave'),
13
+ array('value'=>'EXCLUSIVE_ADD_FROM_MASTER', 'label'=>'Exclusive add from master')
14
+ );
15
+ }
16
+ }
app/code/local/Intuiko/ConnectedStore/Model/Messages.php ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class SearchBagMessage {
4
+ public $type = NULL;
5
+ public $appCustomerId = NULL;
6
+ public $email = NULL;
7
+ public $twitterId = NULL;
8
+
9
+ public function __construct($type, $appCustomerId, $email, $twitterId) {
10
+ $this->type = $type;
11
+ $this->appCustomerId = $appCustomerId;
12
+ $this->email = $email;
13
+ $this->twitterId = $twitterId;
14
+ }
15
+ }
16
+
17
+ class MergeMessage {
18
+ public $masterBagId = NULL;
19
+ public $slaveBagId = NULL;
20
+ public $method = NULL;
21
+
22
+ public function __construct($masterBagId, $slaveBagId, $method) {
23
+ $this->masterBagId = $masterBagId;
24
+ $this->slaveBagId = $slaveBagId;
25
+ $this->method = $method;
26
+ }
27
+ }
28
+
29
+ class DeleteMessage {
30
+ public $bagId = NULL;
31
+
32
+ public function __construct($bagId) {
33
+ $this->bagId = $bagId;
34
+ }
35
+ }
app/code/local/Intuiko/ConnectedStore/Model/Observer.php ADDED
@@ -0,0 +1,417 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ include_once 'Bag.php';
4
+ include_once 'Cart.php';
5
+ include_once 'Wishlist.php';
6
+ include_once 'Order.php';
7
+ include_once 'Messages.php';
8
+ include_once 'app/code/local/Intuiko/ConnectedStore/Logger/ICSLogger.php';
9
+
10
+ class Intuiko_ConnectedStore_Model_Observer extends Varien_Event_Observer {
11
+
12
+ private static $ICSIsLoggedIn = 'ICSIsLoggedIn';
13
+
14
+ const CART_KEY = "cart";
15
+ const WISHLIST_KEY = "wishlist";
16
+ const FORCED_SAVE_KEY = "forcedSave";
17
+
18
+ /**
19
+ * Save a cart in ICS after a cart update.
20
+ * Called on magento event [checkout_cart_save_after].
21
+ */
22
+ public function onSaveCart($observer) {
23
+ if(!Mage::helper('connectedstore/ICSHelper')->isICSModuleEnabled()) {
24
+ return;
25
+ }
26
+
27
+ ICSLogger::debug('*** Beginning SaveCart event (checkout_cart_save_after)');
28
+ $this->performCartSave(Cart::getCartChecksumInSession(), Cart::createCart($observer->getEvent()->_data['cart']->getQuote()));
29
+ }
30
+
31
+ /**
32
+ * Save a wishlist in ICS after a wishlist update.
33
+ * Called on magento event [wishlist_items_renewed].
34
+ */
35
+ public function onSaveWishlist() {
36
+ $customer = Mage::getSingleton('customer/session')->getCustomer();
37
+ $isLoggedIn = Mage::getSingleton('core/session')->getData(self::$ICSIsLoggedIn);
38
+ if(!Mage::helper('connectedstore/ICSHelper')->isICSModuleEnabled() || empty($isLoggedIn) || !$customer->getId()){
39
+ return;
40
+ }
41
+
42
+ ICSLogger::debug('*** Beginning SaveWishlist event (wishlist_items_renewed)');
43
+ $this->performWishlistSave(Wishlist::getWishlistChecksumInSession(), Wishlist::createWishlist($customer, Mage::helper('wishlist')->getWishlist()));
44
+ }
45
+
46
+ /**
47
+ * Save an order in ICS after an order update.
48
+ * Called on magento event [checkout_submit_all_after].
49
+ */
50
+ public function onSaveOrder($observer) {
51
+ if(!Mage::helper('connectedstore/ICSHelper')->isICSModuleEnabled()) {
52
+ return;
53
+ }
54
+
55
+ ICSLogger::debug('*** Beginning SaveOrder event (checkout_submit_all_after)');
56
+
57
+ $bag = Order::createOrder($observer->getEvent()->_data['quote'], $observer->getEvent()->_data['order']);
58
+ $response = Mage::helper('connectedstore/ICSHelper')->save($bag);
59
+
60
+ if(empty($response)) {
61
+ return;
62
+ }
63
+
64
+ Cart::resetIcsInfoInSession();
65
+ }
66
+
67
+ /**
68
+ * Manage login event, to get the customer cart and wishlist.
69
+ * At this point, the customer may have an anonymous bag (stored in the magento session) and/or a non-anonymous bag in the ICS database.
70
+ * Following the cases, this method get the non-anonymous bag, the anonymous one, or merge the two bags to get the final bag of the customer.
71
+ * This final bag is finally imported into the magento's quote and possibly saved again in ICS.
72
+ *
73
+ * Called on magento event [customer_login].
74
+ */
75
+ public function onLogin() {
76
+ $customer = Mage::getSingleton('customer/session')->getCustomer();
77
+ if(!Mage::helper('connectedstore/ICSHelper')->isICSModuleEnabled() || !$customer->getId()) {
78
+ return;
79
+ }
80
+
81
+ $this->sendIcsCustomer($customer);
82
+
83
+ ICSLogger::debug('*** Beginning Login event (customer_login)');
84
+
85
+ $twitterId = Mage::helper('connectedstore/ICSTwitterHelper')->getTwitterId($customer);
86
+ $searchResponseCart = Mage::helper('connectedstore/ICSHelper')->searchBagsIds(Cart::ICS_TYPE, $customer->getId(), $customer->getEmail(), $twitterId);
87
+ $searchResponseWishlist = Mage::helper('connectedstore/ICSHelper')->searchBagsIds(Wishlist::ICS_TYPE, $customer->getId(), $customer->getEmail(), $twitterId);
88
+
89
+ ICSLogger::debug('+ Retrieving cart...');
90
+ if(is_numeric($searchResponseCart) && $searchResponseCart !== -1) {
91
+ return;
92
+ }
93
+ $array = $this->getCartForLogin($customer, $searchResponseCart);
94
+ $bag = $array[self::CART_KEY];
95
+ $forcedSave = $array[self::FORCED_SAVE_KEY];
96
+
97
+ ICSLogger::debug("Importing cart into magento");
98
+ $bag->importIntoMagento($customer);
99
+ $finalBag = Cart::createCart(Mage::getModel('sales/quote')->loadByCustomer($customer));
100
+ $this->performCartSave($bag->getCheckSum(), $finalBag, $forcedSave);
101
+
102
+ ICSLogger::debug('+ Retrieving wishlist...');
103
+ if(is_numeric($searchResponseWishlist) && $searchResponseWishlist !== -1) {
104
+ return;
105
+ }
106
+ $array = $this->getWishlistForLogin($customer, $searchResponseWishlist);
107
+ $bag = $array[self::WISHLIST_KEY];
108
+ $forcedSave = $array[self::FORCED_SAVE_KEY];
109
+
110
+ ICSLogger::debug("Importing wishlist into magento");
111
+ $bag->importIntoMagento($customer);
112
+ $finalBag = Wishlist::createWishlist($customer, Mage::helper('wishlist')->getWishlist());
113
+ $this->performWishlistSave($bag->getCheckSum(), $finalBag, $forcedSave);
114
+
115
+ Mage::getSingleton('core/session')->setData(self::$ICSIsLoggedIn, 1);
116
+ }
117
+
118
+ /**
119
+ * Reset cart and wishlist in session.
120
+ * Called on magento event [customer_logout].
121
+ */
122
+ public function onLogout(){
123
+ if(!Mage::helper('connectedstore/ICSHelper')->isICSModuleEnabled()) {
124
+ return;
125
+ }
126
+
127
+ Cart::resetIcsInfoInSession();
128
+ Wishlist::resetIcsInfoInSession();
129
+ Customer::resetCustomerChecksumInSession();
130
+ Mage::getSingleton('core/session')->setData(self::$ICSIsLoggedIn, 0);
131
+ }
132
+
133
+ /**
134
+ * Check synchronize flag and synchronize cart and wishlist if needed.
135
+ * Called on magento event [controller_action_predispatch].
136
+ */
137
+ public function synchroBag() {
138
+ $customer = Mage::getSingleton('customer/session')->getCustomer();
139
+ $flag = Bag::getIcsFlagSynchroInSession();
140
+ if(!Mage::helper('connectedstore/ICSHelper')->isICSModuleEnabled() || !empty($flag) || !$customer->getId()) {
141
+ return;
142
+ }
143
+
144
+ ICSLogger::debug('*** Beginning SynchroBag event (controller_action_predispatch)');
145
+
146
+ ICSLogger::debug('+ Synchronising cart...');
147
+ $this->synchroCart($customer);
148
+ ICSLogger::debug('+ Synchronising wishlist...');
149
+ $this->synchroWishlist($customer);
150
+ Bag::setIcsFlagSynchroInSession(true);
151
+ }
152
+
153
+ /**
154
+ * Function for enable the next synchronize of bags.
155
+ * Called on magento event [controller_action_layout_generate_blocks_after].
156
+ */
157
+ public function resetFlagSynchro(){
158
+ if(!Mage::helper('connectedstore/ICSHelper')->isICSModuleEnabled()) {
159
+ return;
160
+ }
161
+
162
+ Bag::setIcsFlagSynchroInSession(false);
163
+ }
164
+
165
+ /**
166
+ * Synchronize cart from ICS.
167
+ *
168
+ * @param Mage_Customer_Model_Customer $customer The magento customer
169
+ */
170
+ private function synchroCart($customer) {
171
+ $twitterId = Mage::helper('connectedstore/ICSTwitterHelper')->getTwitterId($customer);
172
+ $searchResponse = Mage::helper('connectedstore/ICSHelper')->searchBagsIds(Cart::ICS_TYPE, $customer->getId(), $customer->getEmail(), $twitterId);
173
+
174
+ if(is_numeric($searchResponse)) {
175
+ return;
176
+ }
177
+
178
+ if(empty($searchResponse)) {
179
+ if(!Mage::helper('connectedstore/ICSHelper')->getIcsFlagError()){
180
+ ICSLogger::debug('No cart found, quote will be flushed');
181
+ Cart::flushCustomerQuote($customer);
182
+ }else{
183
+ ICSLogger::debug("No cart found, response error from ICS.");
184
+ }
185
+
186
+ Cart::resetIcsInfoInSession();
187
+ return;
188
+ }
189
+
190
+ $icsBagId = $searchResponse[0];
191
+ $bagId = Cart::getIcsCartIdInSession();
192
+
193
+ if(!empty($bagId) && $bagId == $icsBagId) {
194
+ $getResponse = Mage::helper('connectedstore/ICSHelper')->getBagById($bagId, Cart::getCartLastUpdateInSession());
195
+ if(!empty($getResponse) && is_numeric($getResponse)) {
196
+ ICSLogger::debug('Cart up to date, nothing is done');
197
+ return;
198
+ }
199
+
200
+ ICSLogger::debug('Cart out of date, it will be updated');
201
+ $bag = Cart::createCartFromJsonObject($getResponse);
202
+ } else {
203
+ ICSLogger::debug('New cart has been found, get request will be sent');
204
+ $bag = Cart::createCartFromJsonObject(Mage::helper('connectedstore/ICSHelper')->getBagById($icsBagId));
205
+ Cart::setIcsCartIdInSession($icsBagId);
206
+ }
207
+
208
+ ICSLogger::debug("Importing cart into magento");
209
+ $bag->importIntoMagento($customer);
210
+ Cart::setCartLastUpdateInSession($bag->lastUpdate);
211
+ $finalBag = Cart::createCart(Mage::getModel('sales/quote')->loadByCustomer($customer));
212
+ $this->performCartSave($bag->getCheckSum(), $finalBag);
213
+ }
214
+
215
+ /**
216
+ * Synchronize wishlist from ICS.
217
+ *
218
+ * @param Mage_Customer_Model_Customer $customer The magento customer
219
+ */
220
+ private function synchroWishlist($customer){
221
+ $twitterId = Mage::helper('connectedstore/ICSTwitterHelper')->getTwitterId($customer);
222
+ $searchResponse = Mage::helper('connectedstore/ICSHelper')->searchBagsIds(Wishlist::ICS_TYPE, $customer->getId(), $customer->getEmail(), $twitterId);
223
+
224
+ if(is_numeric($searchResponse)) {
225
+ return;
226
+ }
227
+
228
+ if(empty($searchResponse)) {
229
+ ICSLogger::debug('No wishlist found, it will be flushed');
230
+ Wishlist::flushWishlist();
231
+ Wishlist::resetIcsInfoInSession();
232
+ return;
233
+ }
234
+
235
+ $icsBagId = $searchResponse[0];
236
+ $bagId = Wishlist::getIcsWishlistIdInSession();
237
+
238
+ if(!empty($bagId) && $bagId == $icsBagId) {
239
+ $getResponse = Mage::helper('connectedstore/ICSHelper')->getBagById($bagId, Wishlist::getWishlistLastUpdateInSession());
240
+ if(!empty($getResponse) && is_numeric($getResponse)) {
241
+ ICSLogger::debug('Wishlist up to date, nothing is done');
242
+ return;
243
+ }
244
+
245
+ ICSLogger::debug('Wishlist out of date, it will be updated');
246
+ $bag = Wishlist::createWishlistFromJsonObject($getResponse);
247
+ } else {
248
+ ICSLogger::debug('New wishlist has been found, get request will be sent');
249
+ $bag = Wishlist::createWishlistFromJsonObject(Mage::helper('connectedstore/ICSHelper')->getBagById($icsBagId));
250
+ Wishlist::setIcsWishlistIdInSession($icsBagId);
251
+ }
252
+
253
+ ICSLogger::debug("Importing wishlist into magento");
254
+ $bag->importIntoMagento($customer);
255
+ $finalBag = Wishlist::createWishlist($customer, Mage::helper('wishlist')->getWishlist());
256
+ Wishlist::setWishlistLastUpdateInSession($bag->lastUpdate);
257
+ $this->performWishlistSave($bag->getCheckSum(), $finalBag);
258
+ }
259
+
260
+ /**
261
+ * Perform a call to the save method of the api if needed.
262
+ * The save is needed if the given bag's checksum is different than the given old checksum.
263
+ *
264
+ * @param String $oldChecksum The old checksum
265
+ * @param Cart $bag The bag to save
266
+ * @param Bool $forcedSave True for the bag to be saved even if the old checksum and the given bag's checksum are the same.
267
+ */
268
+ private function performCartSave($oldChecksum, $bag, $forcedSave = false) {
269
+ if(!is_null($oldChecksum) && strcmp($bag->getCheckSum(), $oldChecksum) == 0 && !$forcedSave) {
270
+ ICSLogger::debug('Cart has not been modified, nothing is done');
271
+ return;
272
+ }
273
+
274
+ ICSLogger::debug('Cart has been modified, save request will be sent');
275
+ $response = Mage::helper('connectedstore/ICSHelper')->save($bag);
276
+
277
+ if(empty($response)) {
278
+ return;
279
+ }
280
+
281
+ $bag->bagId = $response['bagId'];
282
+ Cart::setIcsInfoInSession($response['bagId'], $bag->getCheckSum(), $response['lastUpdate']);
283
+ }
284
+
285
+ /**
286
+ * Perform a call to the save method of the api if needed.
287
+ * The save is needed if the given bag's checksum is different than the old checksum.
288
+ *
289
+ * @param String $oldChecksum The old checksum
290
+ * @param Wishlist $bag The bag to save
291
+ * @param Bool $forcedSave True for the bag to be saved even if the old checksum and the given bag's checksum are the same.
292
+ */
293
+ private function performWishlistSave($oldChecksum, $bag, $forcedSave = false) {
294
+ if(!is_null($oldChecksum) && strcmp($bag->getCheckSum(), $oldChecksum) == 0 && !$forcedSave) {
295
+ ICSLogger::debug('Wishlist has not been modified, nothing is done');
296
+ return;
297
+ }
298
+
299
+ ICSLogger::debug('Wishlist has been modified, save request will be sent');
300
+ $response = Mage::helper('connectedstore/ICSHelper')->save($bag);
301
+
302
+ if(empty($response)) {
303
+ return;
304
+ }
305
+
306
+ $bag->bagId = $response['bagId'];
307
+ Wishlist::setIcsInfoInSession($response['bagId'], $bag->getCheckSum(), $response['lastUpdate']);
308
+ }
309
+
310
+ /**
311
+ * Get an array containing the current cart of the customer and if it must be saved.
312
+ * The cart is retrieved following the different possible cases.
313
+ *
314
+ * @param Mage_Customer_Model_Customer $customer The current customer
315
+ * @param Array $searchResponse The response of a search call
316
+ * @return Array An array containing, for the key "cart" the current cart of the customer,
317
+ * and for the key "forcedSave" a boolean that tells if that cart must be saved.
318
+ */
319
+ private function getCartForLogin($customer, $searchResponse) {
320
+ $bag = new Cart();
321
+ $forcedSave = false;
322
+ $currentBagId = Cart::getIcsCartIdInSession();
323
+
324
+ if($searchResponse === -1 && empty($currentBagId)){
325
+ ICSLogger::debug("Customer not known in ICS");
326
+ $bag = Cart::createCart(Mage::getModel('sales/quote')->loadByCustomer($customer));
327
+ $forcedSave = true;
328
+ }
329
+ else if($searchResponse === -1 && !empty($currentBagId)) {
330
+ ICSLogger::debug('Customer not known in ICS with a cart in magento\'s session');
331
+ $bag = Cart::createCartFromJsonObject(Mage::helper('connectedstore/ICSHelper')->getBagById($currentBagId));
332
+ $forcedSave = true;
333
+ }
334
+ else if(empty($searchResponse) && !empty($currentBagId)) {
335
+ ICSLogger::debug('Customer has a cart in magento\'s session and not in ICS');
336
+ $bag = Cart::createCartFromJsonObject(Mage::helper('connectedstore/ICSHelper')->getBagById($currentBagId));
337
+ $forcedSave = true;
338
+ }
339
+ else if(!empty($searchResponse) && empty($currentBagId)) {
340
+ ICSLogger::debug('Customer has at least one cart in ICS and not in magento\'s session');
341
+ $bag = Cart::createCartFromJsonObject(Mage::helper('connectedstore/ICSHelper')->getBagById($searchResponse[0]));
342
+ Cart::setIcsInfoInSession($bag->bagId, $bag->getCheckSum(), $bag->lastUpdate);
343
+ }
344
+ else if(!empty($searchResponse) && !empty($currentBagId)) {
345
+ ICSLogger::debug('Customer has a cart in magento\'s session and at least one cart in ICS');
346
+ $bag = Cart::createCartFromJsonObject(Mage::helper('connectedstore/ICSHelper')->merge($searchResponse[0], $currentBagId));
347
+ ICSLogger::debug('Merge done, delete request will be sent for the anonymous cart');
348
+ Mage::helper('connectedstore/ICSHelper')->delete($currentBagId);
349
+ Cart::setIcsInfoInSession($bag->bagId, $bag->getCheckSum(), $bag->lastUpdate);
350
+ }
351
+ else if(empty($searchResponse) && empty($currentBagId)) {
352
+ ICSLogger::debug("Customer has no magento cart and no ICS cart");
353
+ Cart::flushCustomerQuote($customer);
354
+ Cart::resetIcsInfoInSession();
355
+ }
356
+
357
+ return array(self::CART_KEY => $bag, self::FORCED_SAVE_KEY => $forcedSave);
358
+ }
359
+
360
+ /**
361
+ * Get an array containing the current wishlist of the customer.
362
+ * The wishlist is retrieved following the different possible cases.
363
+ *
364
+ * @param Mage_Customer_Model_Customer $customer The current customer
365
+ * @param Array $searchResponse The response of a search call
366
+ * @return Array An array containing, for the key "wishlist" the current wishlist of the customer,
367
+ * and for the key "forcedSave" a boolean that tells if that wishlist must be saved.
368
+ */
369
+ private function getWishlistForLogin($customer, $searchResponse) {
370
+ $bag = new Wishlist();
371
+ $forcedSave = false;
372
+
373
+ if($searchResponse === -1){
374
+ ICSLogger::debug("Customer not known in ICS");
375
+ $bag = Wishlist::createWishlist($customer, Mage::helper('wishlist')->getWishlist());
376
+ $forcedSave = true;
377
+ }
378
+ else if(!empty($searchResponse)) {
379
+ ICSLogger::debug('Customer has at least one wishlist in ICS');
380
+ $bag = Wishlist::createWishlistFromJsonObject(Mage::helper('connectedstore/ICSHelper')->getBagById($searchResponse[0]));
381
+ Wishlist::setIcsInfoInSession($bag->bagId, $bag->getCheckSum(), $bag->lastUpdate);
382
+ }
383
+ else if(empty($searchResponse)) {
384
+ ICSLogger::debug("Customer has no ICS wishlist");
385
+ Wishlist::flushWishlist();
386
+ Wishlist::resetIcsInfoInSession();
387
+ }
388
+
389
+ return array(self::WISHLIST_KEY => $bag, self::FORCED_SAVE_KEY => $forcedSave);
390
+ }
391
+
392
+ public function onCustomerSaveAfter() {
393
+ if(!Mage::helper('connectedstore/ICSHelper')->isICSModuleEnabled()) {
394
+ return;
395
+ }
396
+ ICSLogger::debug('*** Beginning SaveCustomer event (customer_save_after)');
397
+ $this->sendIcsCustomer(Mage::getSingleton('customer/session')->getCustomer());
398
+ }
399
+
400
+ private function sendIcsCustomer($customerSession) {
401
+ if($customerSession == null || $customerSession->getId() == null) {
402
+ return;
403
+ }
404
+ $customerToSend = Customer::createIcsCustomer($customerSession);
405
+ $oldChecksum = Customer::getCustomerChecksumInSession();
406
+ $checksum = $customerToSend->getCheckSum();
407
+ ICSLogger::debug("Customer checksum verification");
408
+ if($oldChecksum == null || $oldChecksum != $checksum) {
409
+ ICSLogger::debug("Checksums are not the same. We save.");
410
+ $response = Mage::helper('connectedstore/ICSHelper')->saveCustomer($customerToSend);
411
+ if(empty($response)) {
412
+ return;
413
+ }
414
+ Customer::setCustomerChecksumInSession($checksum);
415
+ }
416
+ }
417
+ }
app/code/local/Intuiko/ConnectedStore/Model/Order.php ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Order extends Bag {
4
+
5
+ /**
6
+ * Default constructor.
7
+ */
8
+ private function __construct() {
9
+ $this->checkFields();
10
+ }
11
+
12
+ /**
13
+ * A static method which instanciates an Order and feeds it with quote information.
14
+ *
15
+ * @param Mage_Sales_Model_Quote $quote The cart's quote
16
+ * @param Mage_Sales_Model_Order $order The order's information
17
+ * @return Cart A new order built from the cart and the checkout information
18
+ */
19
+ public static function createOrder($quote, $order) {
20
+ $bag = new Order();
21
+ $bag->bagType = 'ORDER';
22
+ $bag->constructCartOrOrderFromQuote($quote);
23
+ $bag->setTotalsForOrder($order);
24
+ $bag->paymentMethod = $quote->getPayment()->getMethodInstance()->getTitle();
25
+ $bag->shipmentMethod = $order->getShippingDescription();
26
+ // if guest, special customer method
27
+ if($quote->getData('checkout_method') === Mage_Checkout_Model_Type_Onepage::METHOD_GUEST){
28
+ $bag->customer = $bag->getGuestFromQuote($quote);
29
+ }
30
+ $bag->checkFields();
31
+ return $bag;
32
+ }
33
+
34
+ /**
35
+ * Set the order's totals
36
+ *
37
+ * @param Mage_Sales_Model_Order $order The order
38
+ */
39
+ private function setTotalsForOrder($order) {
40
+ $totals = new Totals();
41
+
42
+ $totals->subtotal = $order->getSubtotal();
43
+ $totals->total = $order->getGrandTotal();
44
+ $totals->discount = $order->getDiscountAmount();
45
+ $totals->shipping = $order->getShippingAmount();
46
+ $totals->vat = $order->getTaxAmount();
47
+ // TODO: vatRate
48
+ $totals->currency = Mage::getStoreConfig(Mage_Directory_Model_Currency::XML_PATH_CURRENCY_BASE);
49
+
50
+ $this->totals = $totals;
51
+ }
52
+ }
app/code/local/Intuiko/ConnectedStore/Model/Resource/ICSResource.php ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class ICSResource {
4
+
5
+ /**
6
+ * Get bundle selection from id
7
+ */
8
+ public static function getSelectionById($selectionId) {
9
+ $resource = Mage::getModel('bundle/option')->getResource();
10
+ $adapter = $resource->getReadConnection();
11
+ $select = $adapter->select()
12
+ ->from('catalog_product_bundle_selection')
13
+ ->where('selection_id = ?', $selectionId);
14
+ return $adapter->fetchRow($select);
15
+ }
16
+ }
app/code/local/Intuiko/ConnectedStore/Model/Wishlist.php ADDED
@@ -0,0 +1,331 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Wishlist extends Bag {
4
+
5
+ protected static $ICS_WishlistId = 'ICS_WishlistId';
6
+ protected static $ICS_WishlistChecksum = 'ICS_WishlistChecksum';
7
+ protected static $ICS_WishlistLastUpdate = 'ICS_WishlistLastUpdate';
8
+ /** Name of the ICS type for cart */
9
+ const ICS_TYPE = 'WISHLIST';
10
+
11
+
12
+ /**
13
+ * Default constructor
14
+ */
15
+ public function __construct() {
16
+ $this->checkFields();
17
+ }
18
+
19
+ /**
20
+ * A static function which instanciates a Wishlist and feeds it current Magento wishlist information
21
+ *
22
+ * @param Mage_Customer_Model_Customer $customer The magento's customer
23
+ * @param Mage_Wishlist_Model_Wishlist $wishlist The magento's wishlist
24
+ * @return Wishlist The ICS wishlist built from the magento's one
25
+ */
26
+ public static function createWishlist($customer, $wishlist) {
27
+ $bag = new Wishlist();
28
+ $bag->bagType = 'WISHLIST';
29
+ $bag->bagName = 'default';
30
+ $bag->constructWishlist($customer, $wishlist);
31
+ $bag->setTotalsForWishlist($wishlist);
32
+ $bag->checkFields();
33
+ return $bag;
34
+ }
35
+
36
+ /**
37
+ * Create a Wishlist from the given json object.
38
+ *
39
+ * @param Object $jsonObject The json stream that represents a wishlist
40
+ * @return Wishlist A wishlist built from the json stream
41
+ */
42
+ public static function createWishlistFromJsonObject($jsonObject) {
43
+ $wishlist = new Wishlist();
44
+
45
+ if(empty($jsonObject)) {
46
+ return $wishlist;
47
+ }
48
+
49
+ $wishlist->createBagFromJsonObject($jsonObject);
50
+ $wishlist->checkFields();
51
+ return $wishlist;
52
+ }
53
+
54
+ /**
55
+ * Set the wishlist's checksum given in parameter in session
56
+ *
57
+ * @param String $checksum The checksum to set in the session
58
+ */
59
+ public static function setWishlistChecksumInSession($checksum){
60
+ Mage::getSingleton('core/session')->setData(self::$ICS_WishlistChecksum, $checksum);
61
+ }
62
+
63
+ /**
64
+ * Get the current wishlist's checksum in session
65
+ *
66
+ * @return String The current wishlist checksum
67
+ */
68
+ public static function getWishlistChecksumInSession(){
69
+ return Mage::getSingleton('core/session')->getData(self::$ICS_WishlistChecksum);
70
+ }
71
+
72
+ /**
73
+ * Set the wishlist id given in parameter in session
74
+ *
75
+ * @param Integer $wishlistId The id to set in the session
76
+ */
77
+ public static function setIcsWishlistIdInSession($wishlistId){
78
+ Mage::getSingleton('core/session')->setData(self::$ICS_WishlistId, $wishlistId);
79
+ }
80
+
81
+ /**
82
+ * Get the wishlist id from the session
83
+ *
84
+ * @return Integer the current wishlist id
85
+ */
86
+ public static function getIcsWishlistIdInSession(){
87
+ return Mage::getSingleton('core/session')->getData(self::$ICS_WishlistId);
88
+ }
89
+
90
+ /**
91
+ * Set the wishlist's date of last update given in parameter in session
92
+ *
93
+ * @param String $date The date to set in the session
94
+ */
95
+ public static function setWishlistLastUpdateInSession($date){
96
+ Mage::getSingleton('core/session')->setData(self::$ICS_WishlistLastUpdate, $date);
97
+ }
98
+
99
+ /**
100
+ * Get the Wishlist's date of last update in session
101
+ *
102
+ * @return String The wishlist's date of last update in session
103
+ */
104
+ public static function getWishlistLastUpdateInSession(){
105
+ return Mage::getSingleton('core/session')->getData(self::$ICS_WishlistLastUpdate);
106
+ }
107
+
108
+ /**
109
+ * Set the several information in session:
110
+ * -> The given wishlistId
111
+ * -> The given checksum
112
+ * -> The given lastUpdate
113
+ *
114
+ * @param Integer $wishlistId The current wishlistId
115
+ * @param String $checksum The wishlist checksum
116
+ * @param String $lastUpdate The wishlist last update
117
+ */
118
+ public static function setIcsInfoInSession($wishlistId, $checksum, $lastUpdate) {
119
+ self::setIcsWishlistIdInSession($wishlistId);
120
+ self::setWishlistChecksumInSession($checksum);
121
+ self::setWishlistLastUpdateInSession($lastUpdate);
122
+ }
123
+
124
+ /**
125
+ * Flush all wishlist information in session
126
+ */
127
+ public static function resetIcsInfoInSession() {
128
+ self::setIcsWishlistIdInSession(null);
129
+ self::setWishlistChecksumInSession(null);
130
+ self::setWishlistLastUpdateInSession(null);
131
+ }
132
+
133
+ /**
134
+ * Flush the wishlist of the current customer.
135
+ */
136
+ public static function flushWishlist(){
137
+ $wishlist = Mage::helper('wishlist')->getWishlist();
138
+ if(is_null($wishlist) || is_null($wishlist->getId())) {
139
+ return;
140
+ }
141
+
142
+ $items = Mage::helper('wishlist')->getWishlistItemCollection();
143
+ foreach($items as $item) {
144
+ Mage::getModel('wishlist/item')->load($item->getId())->delete();
145
+ }
146
+
147
+ $wishlist->save();
148
+ $wishlist = Mage::getModel('wishlist/wishlist')->load($wishlist->getId());
149
+ Mage::unregister('wishlist');
150
+ Mage::register('wishlist', $wishlist);
151
+ }
152
+
153
+ /**
154
+ * Import the current wishlist in the magento's one.
155
+ *
156
+ * @param Mage_Customer_Model_Customer $customer The current customer
157
+ */
158
+ public function importIntoMagento($customer){
159
+ self::flushWishlist();
160
+
161
+ $wishlist = Mage::helper('wishlist')->getWishlist();
162
+ if(is_null($wishlist) || is_null($wishlist->getId())) {
163
+ $wishlist = Mage::getSingleton('wishlist/wishlist')->loadByCustomer($customer, true);
164
+ }
165
+ $wishlist = Mage::getModel('wishlist/wishlist')->load($wishlist->getId());
166
+
167
+ if(!empty($this->bagItems)) {
168
+ foreach($this->bagItems as $bagItem) {
169
+ $productData = $this->getProductDataFromBagItem($bagItem);
170
+
171
+ // Getting product id
172
+ $sku = empty($bagItem->rawData->parentSku) ? $bagItem->skuRef : $bagItem->rawData->parentSku;
173
+ $product = Mage::getModel('catalog/product')->load(Mage::getModel('catalog/product')->getIdBySku($sku));
174
+
175
+ // Wishlist creation
176
+ try {
177
+ $item = $wishlist->addNewItem($product, $productData);
178
+ $item->description = $bagItem->comment;
179
+ } catch (Exception $e) {
180
+ ICSLogger::error('At least one product does not exist in database when loading wishlist : ' . $this->bagId);
181
+ }
182
+
183
+ $wishlist->save();
184
+ }
185
+ }
186
+
187
+ $wishlist->save();
188
+ $wishlist = Mage::getModel('wishlist/wishlist')->load($wishlist->getId());
189
+ Mage::unregister('wishlist');
190
+ Mage::register('wishlist', $wishlist);
191
+ Mage::unregister('_helper/wishlist');
192
+ }
193
+
194
+ /**
195
+ * Construct a bag message for the current customer wishlist
196
+ *
197
+ * @param Mage_Customer_Model_Customer $customer
198
+ * @param Mage_Wishlist_Model_Wishlist $wishlist
199
+ */
200
+ private function constructWishlist($customer, $wishlist) {
201
+ $session = Mage::getSingleton('core/session');
202
+ // We add the customer
203
+ $this->customer = $this->createBagCustomer($customer);
204
+ // We get the context
205
+ $this->context = $this->getContext($session);
206
+
207
+ //set origin
208
+ if(Mage::app()->getRequest()->getModuleName() == 'wishlist' && Mage::app()->getRequest()->getActionName() == 'fromcart'){
209
+ $this->refBagOrigin = Cart::getIcsCartIdInSession();
210
+ }
211
+
212
+ // We get the bagId in session
213
+ $bagId = $session->getData(self::$ICS_WishlistId);
214
+ if($bagId != NULL) {
215
+ $this->bagId = $bagId;
216
+ }
217
+
218
+ $this->bagItems = array();
219
+ foreach($wishlist->getItemCollection() as $item) {
220
+ $product = $item->getProduct();
221
+ $icsItem = $this->getBagItemIcsFromWishlistItem($item);
222
+
223
+ switch ($product->getTypeId()) {
224
+ case Mage_Catalog_Model_Product_Type::TYPE_BUNDLE :
225
+ $key = $this->generateBagItemKeyFromChildren($icsItem);
226
+ break;
227
+ case Mage_Catalog_Model_Product_Type::TYPE_GROUPED :
228
+ $key = $this->generateBagItemKeyFromChildren($icsItem);
229
+ break;
230
+ case Mage_Catalog_Model_Product_Type::TYPE_CONFIGURABLE :
231
+ $key = $this->generateBagItemKeyFromAttributes($icsItem);
232
+ break;
233
+ default:
234
+ $key = str_replace('.', self::DOT_REPLACE, $product->getData('sku'));
235
+ }
236
+
237
+ $this->bagItems[$key] = $icsItem;
238
+ }
239
+ }
240
+
241
+ /**
242
+ * Generate a bagItem from a wishlist item
243
+ *
244
+ * @param Mage_Wishlist_Model_Item $item The magento's item
245
+ * @return BagItem The ICS item built from the magento's one
246
+ */
247
+ private function getBagItemIcsFromWishlistItem($item) {
248
+ $product = $item->getProduct();
249
+ $buyRequest = $item->getBuyRequest()->getData();
250
+
251
+ $bagItem = $this->getIcsItemFromProduct($product, $buyRequest, $item->getData('qty'));
252
+ $bagItem->comment = $item->getDescription();
253
+
254
+ $fullyConfiguredProduct = $this->isAllAttributesSet($buyRequest);
255
+ if(isset($buyRequest['options']) || isset($buyRequest['super_group']) || isset($buyRequest['bundle_option']) || isset($buyRequest['links'])
256
+ || !$fullyConfiguredProduct) {
257
+ $bagItem->rawData->buyRequest = $buyRequest;
258
+
259
+ if(isset($buyRequest['bundle_option'])) {
260
+ $bagItem->innerItems = $this->getIcsItemsFromBundleOptions($buyRequest);
261
+ } else if(isset($buyRequest['super_group'])) {
262
+ $bagItem->innerItems = $this->getIcsItemsFromSuperGroup($buyRequest);
263
+ }
264
+ }
265
+
266
+ if($fullyConfiguredProduct && $product->getTypeId() === Mage_Catalog_Model_Product_Type::TYPE_CONFIGURABLE) {
267
+ $bagItem->rawData->parentSku = $bagItem->skuRef;
268
+ $bagItem->skuRef = $this->getSkuFromConfigurableProduct($product, $buyRequest);
269
+ }
270
+
271
+ return $bagItem;
272
+ }
273
+
274
+ /**
275
+ * Get the child sku from a fully configured product.
276
+ *
277
+ * @param Mage_Catalog_Model_Product $parentProduct The parent product
278
+ * @param Array $buyRequest The item's buy request
279
+ * @return String The child sku if found, the parent one otherwise
280
+ */
281
+ private function getSkuFromConfigurableProduct($parentProduct, $buyRequest) {
282
+ $products = array();
283
+
284
+ if(isset($buyRequest['super_attribute'])) {
285
+ $products = Mage::getModel('catalog/product')->getCollection()->addStoreFilter();
286
+
287
+ foreach($buyRequest['super_attribute'] as $attributeId => $valueId) {
288
+ $code = $this->getAttributeCodeById($attributeId);
289
+ $products = $products->addAttributeToFilter($code, $valueId);
290
+ }
291
+ }
292
+
293
+ $sku = $parentProduct->getSku();
294
+ $parentId = $parentProduct->getId();
295
+ foreach($products as $product) {
296
+ $found = false;
297
+ $parentIds = Mage::getModel('catalog/product_type_configurable')->getParentIdsByChild($product->getData('entity_id'));
298
+ foreach($parentIds as $id) {
299
+ if($parentId == $id) {
300
+ $found = true;
301
+ break;
302
+ }
303
+ }
304
+ if($found) {
305
+ $sku = $product->getSku();
306
+ break;
307
+ }
308
+ }
309
+
310
+ return $sku;
311
+ }
312
+
313
+ /**
314
+ * Set the wishlist's totals
315
+ *
316
+ * @param Mage_Wishlist_Model_Wishlist $wishlist The magento's wishlist
317
+ */
318
+ private function setTotalsForWishlist($wishlist) {
319
+ $totals = new Totals();
320
+
321
+ $totals->total = 0;
322
+ foreach ($wishlist->getItemCollection() as $item) {
323
+ $totals->total = $totals->total + $item->getProduct()->getFinalPrice() * $item->getData('qty');
324
+ }
325
+
326
+ $totals->subtotal = $totals->total;
327
+ $totals->currency = Mage::getStoreConfig(Mage_Directory_Model_Currency::XML_PATH_CURRENCY_BASE);
328
+
329
+ $this->totals = $totals;
330
+ }
331
+ }
app/code/local/Intuiko/ConnectedStore/controllers/PingController.php ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Intuiko_ConnectedStore_PingController extends Mage_Core_Controller_Front_Action {
4
+
5
+ public function indexAction() {
6
+ if(!Mage::helper('connectedstore/ICSHelper')->isIcsModuleStatusEnabled()) {
7
+ $response = 'ICS connector is disabled.';
8
+ } else {
9
+ $pong = $this->pingAction();
10
+ if($pong != NULL) {
11
+ $response = "Success in " . $pong->timeElapsed . " ms! Tenant: " . $pong->tenantName . ", Profile: " . $pong->applicationProfile . ", Version: " . $pong->apiVersion;
12
+ } else {
13
+ $response = "Fail to connect to ICS, please check your configuration.";
14
+ }
15
+ }
16
+
17
+ $this->getResponse()->setBody($response);
18
+ $this->setFlag('', self::FLAG_NO_POST_DISPATCH, true);
19
+ }
20
+
21
+ public function pingAction() {
22
+ return Mage::helper('connectedstore/ICSHelper')->ping();
23
+ }
24
+ }
app/code/local/Intuiko/ConnectedStore/etc/adminhtml.xml ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <config>
3
+ <acl>
4
+ <resources>
5
+ <admin>
6
+ <children>
7
+ <system>
8
+ <children>
9
+ <config>
10
+ <children>
11
+ <connectedstore_section translate="title">
12
+ <title>Ping</title>
13
+ <sort_order>100</sort_order>
14
+ </connectedstore_section>
15
+ </children>
16
+ </config>
17
+ </children>
18
+ </system>
19
+ </children>
20
+ </admin>
21
+ </resources>
22
+ </acl>
23
+ </config>
app/code/local/Intuiko/ConnectedStore/etc/config.xml ADDED
@@ -0,0 +1,136 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <config>
3
+ <modules>
4
+ <Intuiko_ConnectedStore>
5
+ <version>1.0.0</version>
6
+ </Intuiko_ConnectedStore>
7
+ </modules>
8
+
9
+ <frontend>
10
+ <routers>
11
+ <ping>
12
+ <use>standard</use>
13
+ <args>
14
+ <module>Intuiko_ConnectedStore</module>
15
+ <frontName>ping</frontName>
16
+ </args>
17
+ </ping>
18
+ </routers>
19
+
20
+ <events>
21
+ <checkout_cart_save_after>
22
+ <observers>
23
+ <onSaveCart>
24
+ <type>singleton</type>
25
+ <class>Intuiko_ConnectedStore_Model_Observer</class>
26
+ <method>onSaveCart</method>
27
+ </onSaveCart>
28
+ </observers>
29
+ </checkout_cart_save_after>
30
+
31
+ <checkout_submit_all_after>
32
+ <observers>
33
+ <onSaveOrder>
34
+ <type>singleton</type>
35
+ <class>Intuiko_ConnectedStore_Model_Observer</class>
36
+ <method>onSaveOrder</method>
37
+ </onSaveOrder>
38
+ </observers>
39
+ </checkout_submit_all_after>
40
+
41
+ <wishlist_items_renewed>
42
+ <observers>
43
+ <onSaveWishlist>
44
+ <type>singleton</type>
45
+ <class>Intuiko_ConnectedStore_Model_Observer</class>
46
+ <method>onSaveWishlist</method>
47
+ </onSaveWishlist>
48
+ </observers>
49
+ </wishlist_items_renewed>
50
+
51
+ <customer_login>
52
+ <observers>
53
+ <onLogin>
54
+ <type>singleton</type>
55
+ <class>Intuiko_ConnectedStore_Model_Observer</class>
56
+ <method>onLogin</method>
57
+ </onLogin>
58
+ </observers>
59
+ </customer_login>
60
+
61
+ <customer_logout>
62
+ <observers>
63
+ <onLogout>
64
+ <type>singleton</type>
65
+ <class>Intuiko_ConnectedStore_Model_Observer</class>
66
+ <method>onLogout</method>
67
+ </onLogout>
68
+ </observers>
69
+ </customer_logout>
70
+
71
+ <customer_save_after>
72
+ <observers>
73
+ <onCustomerSaveAfter>
74
+ <type>singleton</type>
75
+ <class>Intuiko_ConnectedStore_Model_Observer</class>
76
+ <method>onCustomerSaveAfter</method>
77
+ </onCustomerSaveAfter>
78
+ </observers>
79
+ </customer_save_after>
80
+
81
+ <controller_action_predispatch>
82
+ <observers>
83
+ <synchroCart>
84
+ <type>singleton</type>
85
+ <class>Intuiko_ConnectedStore_Model_Observer</class>
86
+ <method>synchroBag</method>
87
+ </synchroCart>
88
+ </observers>
89
+ </controller_action_predispatch>
90
+
91
+
92
+ <controller_action_layout_generate_blocks_after>
93
+ <observers>
94
+ <synchroCart>
95
+ <type>singleton</type>
96
+ <class>Intuiko_ConnectedStore_Model_Observer</class>
97
+ <method>resetFlagSynchro</method>
98
+ </synchroCart>
99
+ </observers>
100
+ </controller_action_layout_generate_blocks_after>
101
+
102
+ </events>
103
+
104
+ </frontend>
105
+
106
+ <global>
107
+
108
+ <helpers>
109
+ <connectedstore>
110
+ <class>Intuiko_ConnectedStore_Helper</class>
111
+ </connectedstore>
112
+ </helpers>
113
+
114
+ <models>
115
+ <connectedstore>
116
+ <class>Intuiko_ConnectedStore_Model</class>
117
+ </connectedstore>
118
+ </models>
119
+
120
+ <blocks>
121
+ <connectedstore>
122
+ <class>Intuiko_ConnectedStore_Block</class>
123
+ </connectedstore>
124
+ </blocks>
125
+
126
+ </global>
127
+
128
+ <default>
129
+ <connectedstore_section>
130
+ <connectedstore_group>
131
+ <timeout_field>5000</timeout_field>
132
+ </connectedstore_group>
133
+ </connectedstore_section>
134
+ </default>
135
+
136
+ </config>
app/code/local/Intuiko/ConnectedStore/etc/system.xml ADDED
@@ -0,0 +1,107 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <config>
3
+ <tabs>
4
+ <connectedstore_tab translate="label">
5
+ <label>Connected Store</label>
6
+ <sort_order>100</sort_order>
7
+ </connectedstore_tab>
8
+ </tabs>
9
+ <sections>
10
+ <connectedstore_section translate="label">
11
+ <label>Parameters</label>
12
+ <sort_order>200</sort_order>
13
+ <show_in_default>1</show_in_default>
14
+ <show_in_website>1</show_in_website>
15
+ <show_in_store>1</show_in_store>
16
+ <tab>connectedstore_tab</tab>
17
+ <groups>
18
+ <connectedstore_group translate="label">
19
+ <label>Connected Store</label>
20
+ <comment>Connection parameters</comment>
21
+ <sort_order>10</sort_order>
22
+ <show_in_default>1</show_in_default>
23
+ <show_in_website>1</show_in_website>
24
+ <show_in_store>1</show_in_store>
25
+ <fields>
26
+ <status_field translate="label tooltip">
27
+ <label>ICS Connector Status</label>
28
+ <tooltip>Activate or Deactivate the ICS connector</tooltip>
29
+ <show_in_default>1</show_in_default>
30
+ <show_in_website>1</show_in_website>
31
+ <show_in_store>1</show_in_store>
32
+ <frontend_type>select</frontend_type>
33
+ <source_model>Mage_Adminhtml_Model_System_Config_Source_Enabledisable</source_model>
34
+ <sort_order>1</sort_order>
35
+ </status_field>
36
+ <tenantid_field translate="label tooltip">
37
+ <label>Tenant Id</label>
38
+ <tooltip>Your tenant Id</tooltip>
39
+ <show_in_default>1</show_in_default>
40
+ <show_in_website>1</show_in_website>
41
+ <show_in_store>1</show_in_store>
42
+ <frontend_input>text</frontend_input>
43
+ <sort_order>2</sort_order>
44
+ </tenantid_field>
45
+ <urlservice_field translate="label tooltip">
46
+ <label>Url Service</label>
47
+ <tooltip>The url of the service</tooltip>
48
+ <show_in_default>1</show_in_default>
49
+ <show_in_website>1</show_in_website>
50
+ <show_in_store>1</show_in_store>
51
+ <frontend_input>text</frontend_input>
52
+ <sort_order>3</sort_order>
53
+ </urlservice_field>
54
+ <brandid_field translate="label tooltip">
55
+ <label>Brand Id</label>
56
+ <tooltip>Your Brand Id</tooltip>
57
+ <show_in_default>1</show_in_default>
58
+ <show_in_website>1</show_in_website>
59
+ <show_in_store>1</show_in_store>
60
+ <frontend_input>text</frontend_input>
61
+ <sort_order>4</sort_order>
62
+ </brandid_field>
63
+ <apikey_field translate="label tooltip">
64
+ <label>Api Key</label>
65
+ <tooltip>Your API Key</tooltip>
66
+ <show_in_default>1</show_in_default>
67
+ <show_in_website>1</show_in_website>
68
+ <show_in_store>0</show_in_store>
69
+ <frontend_input>text</frontend_input>
70
+ <sort_order>5</sort_order>
71
+ </apikey_field>
72
+ <mergemethod_field translate="label tooltip">
73
+ <label>Bag Merge Method</label>
74
+ <tooltip>Your bag merge method</tooltip>
75
+ <show_in_default>1</show_in_default>
76
+ <show_in_website>1</show_in_website>
77
+ <show_in_store>0</show_in_store>
78
+ <frontend_type>select</frontend_type>
79
+ <source_model>Intuiko_ConnectedStore_Model_MergeMethods</source_model>
80
+ <sort_order>6</sort_order>
81
+ </mergemethod_field>
82
+ <timeout_field translate="label tooltip">
83
+ <label>ICS API Calls Timeout (ms)</label>
84
+ <tooltip>value in millisecond(s)</tooltip>
85
+ <validate>validate-not-negative-number</validate>
86
+ <show_in_default>1</show_in_default>
87
+ <show_in_website>1</show_in_website>
88
+ <show_in_store>0</show_in_store>
89
+ <frontend_input>int</frontend_input>
90
+ <sort_order>7</sort_order>
91
+ </timeout_field>
92
+ <ping_field translate="label tooltip">
93
+ <!-- <tooltip><![CDATA[Do a ping in order to test your connection to the ICS API.<br/> Note: Do not forget to save your last modifications before running this test.]]></tooltip> -->
94
+ <label><![CDATA[Test your connection<br/> Note: Do not forget to save your last modifications before running this test.]]></label>
95
+ <show_in_default>1</show_in_default>
96
+ <show_in_website>1</show_in_website>
97
+ <show_in_store>0</show_in_store>
98
+ <frontend_input>button</frontend_input>
99
+ <sort_order>8</sort_order>
100
+ <frontend_model>connectedstore/button</frontend_model>
101
+ </ping_field>
102
+ </fields>
103
+ </connectedstore_group>
104
+ </groups>
105
+ </connectedstore_section>
106
+ </sections>
107
+ </config>
app/etc/modules/Intuiko_All.xml ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <config>
3
+ <modules>
4
+ <Intuiko_ConnectedStore>
5
+ <active>true</active>
6
+ <codePool>local</codePool>
7
+ </Intuiko_ConnectedStore>
8
+ </modules>
9
+ </config>
package.xml ADDED
@@ -0,0 +1,2 @@
 
 
1
+ <?xml version="1.0"?>
2
+ <package><name>ICS_Connector</name><version>1.3.1</version><stability>stable</stability><license>MPL</license><channel>community</channel><extends></extends><summary>The Magento Connector developed alongside Intuiko for Connected Store is a two-way connector.</summary><description>The Magento Connector developed alongside Intuiko for Connected Store is a two-way connector.&amp;#xD;Intuiko has developed a module that allows you to manage carts and wishlists from a Magento webiste which uses the Intuiko for Connected Store API.&amp;#xD;</description><notes>Version 1.3.1.</notes><authors><author><name>Intuiko</name><user>Intuiko</user><email>support.ics@intuiko.com</email></author></authors><date>2014-12-01</date><time>0:48:05</time><compatible></compatible><dependencies><required><php><min>5.0.0</min><max>6.0.0</max></php></required></dependencies><contents><target name="mage"><dir name="app"><dir name="etc"><dir name="modules"><file name="Intuiko_All.xml" hash="335ba38d9a767e0cb30c0dc69067652d"/></dir></dir><dir name="code"><dir name="local"><dir name="Intuiko"><dir name="ConnectedStore"><file name="Exception.php" hash="ff373acc5dbd57184595ed7ef2c99426"/><dir name="controllers"><file name="PingController.php" hash="d6fe17473922d65b49a9928a7a299d70"/></dir><dir name="Model"><file name="Bag.php" hash="4eee9a59f438c978e4457d895dd7df5c"/><file name="Cart.php" hash="ecc51597ff0558aae69d70195b033414"/><file name="Customer.php" hash="3338d954f9b67eaacc5d6d50c4d3bb03"/><file name="Entities.php" hash="2e7973982f97c7996219f247106e4665"/><file name="MergeMethods.php" hash="a56c244e7320557556ddf3d445f2ccc9"/><file name="Messages.php" hash="cec65dce8066fb0a16d7bc06585b269e"/><file name="Observer.php" hash="4e33b2276335b21e2331fb74b45acdf1"/><file name="Order.php" hash="758d1c4dcc51e773d05a67f9b2dc06ce"/><file name="Wishlist.php" hash="9475611fc24b04a4ae02d7cdf7083195"/><dir name="Resource"><file name="ICSResource.php" hash="df0d7c0cac29dfb09fa68ac4c055fed5"/></dir></dir><dir name="etc"><file name="adminhtml.xml" hash="08bc5ce6d52b3d3dff3d00dc5e5e3b9d"/><file name="config.xml" hash="d2c80100bda8a1ebb66933fb3875bdd2"/><file name="system.xml" hash="031a4b2c1b93687d4e8f81a22a9fe9a9"/></dir><dir name="Helper"><file name="ICSHelper.php" hash="e22435138ab252ab6cb9e033b8f82562"/><file name="ICSTwitterHelper.php" hash="e0b970d299200a0987b853a6f7120d5c"/></dir><dir name="Block"><file name="Button.php" hash="b266514f04677886a8b23a3311338570"/></dir><dir name="Logger"><file name="ICSLogger.php" hash="8cf2fc0098040f94c5fdd158be269497"/></dir></dir></dir></dir></dir></dir></target></contents></package>