Me_Gravity - Version 1.1.0.2

Version Notes

Version number: 1.1.0.2
Stability: Stable
Compatibility: CE 1.6.x, 1.7.x, 1.8.x, 1.9.x

Download this release

Release Info

Developer Gravity Recommendations
Extension Me_Gravity
Version 1.1.0.2
Comparing to
See all releases


Code changes from version 1.1.0.1 to 1.1.0.2

app/code/community/Me/Gravity/Block/Adminhtml/System/Config/Form/Synch.php ADDED
@@ -0,0 +1,93 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Class Me_Gravity_Block_Adminhtml_System_Config_Form_Test
4
+ *
5
+ * @category Me
6
+ * @package Me_Gravity
7
+ * @author Attila S�gi <sagi.attila@magevolve.com>
8
+ * @copyright 2015 Magevolve Ltd. (http://magevolve.com)
9
+ * @license http://magevolve.com/terms-and-conditions Magevolve Ltd. License
10
+ * @link http://magevolve.com
11
+ */
12
+
13
+ /**
14
+ * Class Me_Gravity_Block_Adminhtml_System_Config_Form_Test
15
+ */
16
+ class Me_Gravity_Block_Adminhtml_System_Config_Form_Synch extends Mage_Adminhtml_Block_System_Config_Form_Field
17
+ {
18
+ /**
19
+ * Construct
20
+ *
21
+ * @return void
22
+ */
23
+ protected function _construct()
24
+ {
25
+ parent::_construct();
26
+ $this->setTemplate('me/gravity/system/config/form/synch.phtml');
27
+ }
28
+
29
+ /**
30
+ * Return element html
31
+ *
32
+ * @param Varien_Data_Form_Element_Abstract $element element
33
+ * @return string
34
+ */
35
+ protected function _getElementHtml(Varien_Data_Form_Element_Abstract $element)
36
+ {
37
+ return $this->_toHtml();
38
+ }
39
+
40
+ /**
41
+ * Return ajax url for button
42
+ *
43
+ * @return string
44
+ */
45
+ public function getAjaxTestUrl()
46
+ {
47
+ return Mage::helper('adminhtml')->getUrl('adminhtml/gravity/test');
48
+ }
49
+
50
+ /**
51
+ * Generate button html
52
+ *
53
+ * @return string
54
+ */
55
+ public function getButtonHtml()
56
+ {
57
+ $button = $this->getLayout()->createBlock('adminhtml/widget_button')
58
+ ->setData(
59
+ array(
60
+ 'id' => 'gravity_test_button',
61
+ 'label' => $this->_getGravityHelper()->__('Test Connection'),
62
+ 'onclick' => 'javascript:check(); return false;',
63
+ 'disabled' => $this->_getIsButtonEnabled()
64
+ )
65
+ );
66
+
67
+ return $button->toHtml();
68
+ }
69
+
70
+ /**
71
+ * Check if button enabled
72
+ *
73
+ * @return bool
74
+ */
75
+ private function _getIsButtonEnabled()
76
+ {
77
+ if ($this->_getGravityHelper()->isFullyEnabled()) {
78
+ return false;
79
+ } else {
80
+ return true;
81
+ }
82
+ }
83
+
84
+ /**
85
+ * Get Gravity extension helper
86
+ *
87
+ * @return Me_Gravity_Helper_Data
88
+ */
89
+ public function _getGravityHelper()
90
+ {
91
+ return Mage::helper('me_gravity');
92
+ }
93
+ }
app/code/community/Me/Gravity/Helper/Data.php CHANGED
@@ -41,7 +41,7 @@ class Me_Gravity_Helper_Data extends Mage_Core_Helper_Data
41
  *
42
  * @var string
43
  */
44
- const XML_PATH_DEBUG = 'gravity/debug/log';
45
 
46
  /**
47
  * Path to store config API username
@@ -62,14 +62,14 @@ class Me_Gravity_Helper_Data extends Mage_Core_Helper_Data
62
  *
63
  * @var string
64
  */
65
- const XML_PATH_CUSTOM_JS_ENABLED = 'gravity/config/enabled_js';
66
 
67
  /**
68
  * Path to store config custom Gravity JS
69
  *
70
  * @var string
71
  */
72
- const XML_PATH_CUSTOM_JS = 'gravity/config/custom_js';
73
 
74
  /**
75
  * Path to store config catalog export path
@@ -83,14 +83,14 @@ class Me_Gravity_Helper_Data extends Mage_Core_Helper_Data
83
  *
84
  * @var string
85
  */
86
- const XML_PATH_USE_TEMPLATE = 'gravity/config/template';
87
 
88
  /**
89
  * Path to store config use bulk recommendation
90
  *
91
  * @var string
92
  */
93
- const XML_PATH_USE_BULK = 'gravity/config/bulk';
94
 
95
  /**
96
  * Path to store config catalog export all
@@ -139,7 +139,7 @@ class Me_Gravity_Helper_Data extends Mage_Core_Helper_Data
139
  *
140
  * @var string
141
  */
142
- const XML_PATH_EXPORT_CATALOG_ADDITIONAL = 'gravity/export/additional';
143
 
144
  /**
145
  * Path to store config additional customer attributes for export
@@ -153,7 +153,7 @@ class Me_Gravity_Helper_Data extends Mage_Core_Helper_Data
153
  *
154
  * @var string
155
  */
156
- const XML_PATH_EXPORT_ONLY_SALABLE = 'gravity/export/only_salable';
157
 
158
  /**
159
  * Path to store config product status parameter for export
@@ -445,7 +445,7 @@ class Me_Gravity_Helper_Data extends Mage_Core_Helper_Data
445
  */
446
  public function useGravityTemplate($store = null)
447
  {
448
- return Mage::getStoreConfigFlag(self::XML_PATH_USE_TEMPLATE, $store);
449
  }
450
 
451
  /**
41
  *
42
  * @var string
43
  */
44
+ const XML_PATH_DEBUG = 'gravity/advanced/log';
45
 
46
  /**
47
  * Path to store config API username
62
  *
63
  * @var string
64
  */
65
+ const XML_PATH_CUSTOM_JS_ENABLED = 'gravity/advanced/enabled_js';
66
 
67
  /**
68
  * Path to store config custom Gravity JS
69
  *
70
  * @var string
71
  */
72
+ const XML_PATH_CUSTOM_JS = 'gravity/advanced/custom_js';
73
 
74
  /**
75
  * Path to store config catalog export path
83
  *
84
  * @var string
85
  */
86
+ const XML_PATH_USE_TEMPLATE = 'gravity/advanced/template';
87
 
88
  /**
89
  * Path to store config use bulk recommendation
90
  *
91
  * @var string
92
  */
93
+ const XML_PATH_USE_BULK = 'gravity/advanced/bulk';
94
 
95
  /**
96
  * Path to store config catalog export all
139
  *
140
  * @var string
141
  */
142
+ const XML_PATH_EXPORT_CATALOG_ADDITIONAL = 'gravity/sync/additional';
143
 
144
  /**
145
  * Path to store config additional customer attributes for export
153
  *
154
  * @var string
155
  */
156
+ const XML_PATH_EXPORT_ONLY_SALABLE = 'gravity/sync/only_salable';
157
 
158
  /**
159
  * Path to store config product status parameter for export
445
  */
446
  public function useGravityTemplate($store = null)
447
  {
448
+ return 0;
449
  }
450
 
451
  /**
app/code/community/Me/Gravity/Model/Export/Catalog/Product.php CHANGED
@@ -197,6 +197,7 @@ class Me_Gravity_Model_Export_Catalog_Product extends Me_Gravity_Model_Export_Ab
197
 
198
  foreach ($collection as $category) {
199
  $structure = preg_split('#/+#', $category->getPath());
 
200
  $pathSize = count($structure);
201
  if ($pathSize > 1) {
202
  $path = array();
197
 
198
  foreach ($collection as $category) {
199
  $structure = preg_split('#/+#', $category->getPath());
200
+
201
  $pathSize = count($structure);
202
  if ($pathSize > 1) {
203
  $path = array();
app/code/community/Me/Gravity/Model/Method/Request.php CHANGED
@@ -41,6 +41,7 @@ class Me_Gravity_Model_Method_Request extends Me_Gravity_Model_Method_Abstract
41
  * Update / add event type
42
  */
43
  const EVENT_TYPE_UPDATE = 'UPDATE';
 
44
 
45
  /**
46
  * Event type customer update
@@ -160,6 +161,8 @@ class Me_Gravity_Model_Method_Request extends Me_Gravity_Model_Method_Abstract
160
  *
161
  * @return void
162
  */
 
 
163
  public function _construct()
164
  {
165
  parent::_construct();
@@ -364,7 +367,23 @@ class Me_Gravity_Model_Method_Request extends Me_Gravity_Model_Method_Abstract
364
  if ($this->_helper->getDebugMode()) {
365
  $this->_helper->getLogger($params);
366
  }
367
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
368
  $userId = $this->_getCustomerId();
369
  $cookieId = $this->_gravityCookie;
370
  $recommendationContext = new GravityRecommendationContext();
@@ -377,10 +396,12 @@ class Me_Gravity_Model_Method_Request extends Me_Gravity_Model_Method_Abstract
377
  }
378
 
379
  $storeValue = new GravityNameValue('storeId', $this->_storeId);
380
- $recommendationContext->nameValues = array($storeValue);
 
 
381
 
382
  if (isset($params['itemId']) && $params['itemId']) {
383
- $pageItemId = new GravityNameValue('currentItemId', $params['itemId']);
384
  $recommendationContext->nameValues = array_merge(array($pageItemId), $recommendationContext->nameValues);
385
  }
386
 
@@ -440,7 +461,23 @@ class Me_Gravity_Model_Method_Request extends Me_Gravity_Model_Method_Abstract
440
  if ($this->_helper->getDebugMode()) {
441
  $this->_helper->getLogger($params);
442
  }
443
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
444
  $recommendationContextArray = array();
445
  $userId = $this->_getCustomerId();
446
  $cookieId = $this->_gravityCookie;
@@ -462,10 +499,12 @@ class Me_Gravity_Model_Method_Request extends Me_Gravity_Model_Method_Abstract
462
  }
463
 
464
  $storeValue = new GravityNameValue('storeId', $this->_storeId);
465
- $recommendationContext->nameValues = array($storeValue);
 
 
466
 
467
  if (isset($param['itemId']) && $param['itemId']) {
468
- $pageItemId = new GravityNameValue('currentItemId', $param['itemId']);
469
  $recommendationContext->nameValues = array_merge(array($pageItemId), $recommendationContext->nameValues);
470
  }
471
 
@@ -542,7 +581,7 @@ class Me_Gravity_Model_Method_Request extends Me_Gravity_Model_Method_Abstract
542
  $item = new GravityItem();
543
  $item->itemId = $params['itemid'];
544
  if ($params['storeId'] == 1) {
545
- $item->title = $params['title'];
546
  }
547
  $item->hidden = $params['hidden'];
548
  if ($this->_canDebugLog) {
@@ -552,20 +591,27 @@ class Me_Gravity_Model_Method_Request extends Me_Gravity_Model_Method_Abstract
552
  unset($params['type']);
553
  unset($params['itemid']);
554
  unset($params['hidden']);
 
555
  //$item->nameValues[] = new GravityNameValue("log", "".var_export($params,true));
556
  foreach ($params as $attribute => $value) {
557
  if ($value) {
558
  //$item->nameValues[] = new GravityNameValue($attribute, $value);
559
  //foreach ($stores as $store) {
560
  if ($params['storeId'] != 0) {
561
- $item->nameValues[] = new GravityNameValue($attribute."_".$params['storeId'], $value);
 
 
 
562
  } else {
563
- $item->nameValues[] = new GravityNameValue($attribute, $value);
 
 
 
564
  }
565
  }
566
  }
567
  $isAsync = true;
568
- $result = $client->updateItem($item, $isAsync);
569
 
570
  } else {
571
  Mage::throwException($this->_helper->__('Invalid ' . $params['type'] . ' parameters'));
41
  * Update / add event type
42
  */
43
  const EVENT_TYPE_UPDATE = 'UPDATE';
44
+
45
 
46
  /**
47
  * Event type customer update
161
  *
162
  * @return void
163
  */
164
+
165
+
166
  public function _construct()
167
  {
168
  parent::_construct();
367
  if ($this->_helper->getDebugMode()) {
368
  $this->_helper->getLogger($params);
369
  }
370
+ $collection = Mage::getResourceModel('catalog/category_collection')
371
+ ->setStoreId($this->_storeId)
372
+ ->addNameToResult();
373
+ $layer = Mage::getSingleton('catalog/layer');
374
+ if(isset($layer)){
375
+ $_category = $layer->getCurrentCategory();
376
+ $currentCategoryId= $_category->getId();
377
+ $_cat = Mage::getModel('catalog/category')->load($currentCategoryId);
378
+ $structure = preg_split('#/+#', $_cat->getPath());
379
+ for($j=0; $j<count($structure); $j=$j+1){
380
+ $structure[$j]=$collection->getItemById($structure[$j])->getName();
381
+ }
382
+ $currentCategoryPath = implode("/", $structure);
383
+ }else{
384
+ $currentCategoryId='';
385
+ $currentCategoryPath='';
386
+ }
387
  $userId = $this->_getCustomerId();
388
  $cookieId = $this->_gravityCookie;
389
  $recommendationContext = new GravityRecommendationContext();
396
  }
397
 
398
  $storeValue = new GravityNameValue('storeId', $this->_storeId);
399
+ $categoryId = new GravityNameValue('categoryId', $currentCategoryId);
400
+ $categoryPath = new GravityNameValue('categoryPath', $currentCategoryPath);
401
+ $recommendationContext->nameValues = array($storeValue,$categoryId,$categoryPath);
402
 
403
  if (isset($params['itemId']) && $params['itemId']) {
404
+ $pageItemId = new GravityNameValue('itemId', $params['itemId']);
405
  $recommendationContext->nameValues = array_merge(array($pageItemId), $recommendationContext->nameValues);
406
  }
407
 
461
  if ($this->_helper->getDebugMode()) {
462
  $this->_helper->getLogger($params);
463
  }
464
+ $collection = Mage::getResourceModel('catalog/category_collection')
465
+ ->setStoreId($this->_storeId)
466
+ ->addNameToResult();
467
+ $layer = Mage::getSingleton('catalog/layer');
468
+ if(isset($layer)){
469
+ $_category = $layer->getCurrentCategory();
470
+ $currentCategoryId= $_category->getId();
471
+ $_cat = Mage::getModel('catalog/category')->load($currentCategoryId);
472
+ $structure = preg_split('#/+#', $_cat->getPath());
473
+ for($j=0; $j<count($structure); $j=$j+1){
474
+ $structure[$j]=$collection->getItemById($structure[$j])->getName();
475
+ }
476
+ $currentCategoryPath = implode("/", $structure);
477
+ }else{
478
+ $currentCategoryId='';
479
+ $currentCategoryPath='';
480
+ }
481
  $recommendationContextArray = array();
482
  $userId = $this->_getCustomerId();
483
  $cookieId = $this->_gravityCookie;
499
  }
500
 
501
  $storeValue = new GravityNameValue('storeId', $this->_storeId);
502
+ $categoryId = new GravityNameValue('categoryId', $currentCategoryId);
503
+ $categoryPath = new GravityNameValue('categoryPath', $currentCategoryPath);
504
+ $recommendationContext->nameValues = array($storeValue,$categoryId,$categoryPath);
505
 
506
  if (isset($param['itemId']) && $param['itemId']) {
507
+ $pageItemId = new GravityNameValue('itemId', $param['itemId']);
508
  $recommendationContext->nameValues = array_merge(array($pageItemId), $recommendationContext->nameValues);
509
  }
510
 
581
  $item = new GravityItem();
582
  $item->itemId = $params['itemid'];
583
  if ($params['storeId'] == 1) {
584
+ // $item->title = $params['title'];
585
  }
586
  $item->hidden = $params['hidden'];
587
  if ($this->_canDebugLog) {
591
  unset($params['type']);
592
  unset($params['itemid']);
593
  unset($params['hidden']);
594
+
595
  //$item->nameValues[] = new GravityNameValue("log", "".var_export($params,true));
596
  foreach ($params as $attribute => $value) {
597
  if ($value) {
598
  //$item->nameValues[] = new GravityNameValue($attribute, $value);
599
  //foreach ($stores as $store) {
600
  if ($params['storeId'] != 0) {
601
+ foreach($value as $val){
602
+ array_push($item->nameValues, new GravityNameValue($attribute, $val));
603
+ }
604
+ //$item->nameValues[] = new GravityNameValue($attribute, $value);
605
  } else {
606
+ //$item->nameValues[] = new GravityNameValue($attribute, $value);
607
+ foreach($value as $val){
608
+ array_push($item->nameValues, new GravityNameValue($attribute, $val));
609
+ }
610
  }
611
  }
612
  }
613
  $isAsync = true;
614
+ $result = $client->addItem($item, $isAsync);
615
 
616
  } else {
617
  Mage::throwException($this->_helper->__('Invalid ' . $params['type'] . ' parameters'));
app/code/community/Me/Gravity/Model/Observer.php CHANGED
@@ -20,6 +20,8 @@ class Me_Gravity_Model_Observer
20
  *
21
  * @var array
22
  */
 
 
23
  protected $_productRecommendationTypes = array(
24
  'similar' => Me_Gravity_Model_Method_Request::PRODUCT_PAGE_SIMILAR,
25
  'personal' => Me_Gravity_Model_Method_Request::PRODUCT_PAGE_PERSONAL,
@@ -55,6 +57,7 @@ class Me_Gravity_Model_Observer
55
  */
56
  protected $_filters = null;
57
 
 
58
  /**
59
  * Add Gravity block to catalog product view
60
  *
@@ -358,13 +361,19 @@ class Me_Gravity_Model_Observer
358
 
359
  $customer = $observer->getCustomer();
360
  if (!is_null($customer) && $customer->getId()) {
361
-
 
 
 
 
 
 
362
  $parameters = array(
363
  'type' => Me_Gravity_Model_Method_Request::EVENT_TYPE_CUSTOMER_UPDATE,
364
  'userid' => $customer->getId(),
365
  'email' => $customer->getEmail(),
366
- 'firstname' => $customer->getFirstname(),
367
- 'lastname' => $customer->getLastname()
368
  );
369
 
370
  Mage::getModel('me_gravity/method_request')->sendRequest(
@@ -385,20 +394,63 @@ class Me_Gravity_Model_Observer
385
 
386
  return $this;
387
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
388
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
389
  /**
390
  * Gravity product update event observer
391
  *
392
  * @param Varien_Event_Observer $observer observer
393
  * @return $this
394
  */
395
- public function gravityProductUpdate(Varien_Event_Observer $observer)
396
- {
397
- if (!$this->_getGravityHelper()->isFullyEnabled() || !$this->_getGravityHelper()->getProductUpdateEnabled()) {
 
 
398
  return false;
399
  }
400
-
401
- try {
402
  $storeId = Mage::app()->getDefaultStoreView()->getId();
403
  $param = Mage::app()->getRequest()->getParam('store');
404
  if (isset($param) && $param) {
@@ -414,7 +466,7 @@ class Me_Gravity_Model_Observer
414
  'type' => Me_Gravity_Model_Method_Request::EVENT_TYPE_PRODUCT_UPDATE,
415
  'itemid' => $product->getId(),
416
  'title' => htmlspecialchars($product->getName()),
417
- 'hidden' => ($product->getVisibility() == Mage_Catalog_Model_Product_Visibility::VISIBILITY_NOT_VISIBLE) ? 'true' : 'false',
418
  'link' => $productUrl ? $productUrl : $product->getProductUrl(),
419
  'image_link' => htmlspecialchars($this->_getCatalogBaseMediaUrl() . $product->getImage()),
420
  'description' => htmlspecialchars($product->getDescription()),
@@ -446,6 +498,81 @@ class Me_Gravity_Model_Observer
446
  }
447
 
448
  return $this;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
449
  }
450
 
451
  /**
20
  *
21
  * @var array
22
  */
23
+
24
+
25
  protected $_productRecommendationTypes = array(
26
  'similar' => Me_Gravity_Model_Method_Request::PRODUCT_PAGE_SIMILAR,
27
  'personal' => Me_Gravity_Model_Method_Request::PRODUCT_PAGE_PERSONAL,
57
  */
58
  protected $_filters = null;
59
 
60
+
61
  /**
62
  * Add Gravity block to catalog product view
63
  *
361
 
362
  $customer = $observer->getCustomer();
363
  if (!is_null($customer) && $customer->getId()) {
364
+ if($customer->getGender()==1){
365
+ $gender = 'male';
366
+ }elseif($customer->getGender()==2){
367
+ $gender = 'female';
368
+ }else{
369
+ $gender = 'not specified';
370
+ }
371
  $parameters = array(
372
  'type' => Me_Gravity_Model_Method_Request::EVENT_TYPE_CUSTOMER_UPDATE,
373
  'userid' => $customer->getId(),
374
  'email' => $customer->getEmail(),
375
+ 'name' => $customer->getName(),
376
+ 'sex' => $gender
377
  );
378
 
379
  Mage::getModel('me_gravity/method_request')->sendRequest(
394
 
395
  return $this;
396
  }
397
+
398
+
399
+ public function gravityCustomerSave(arien_Event_Observer $observer){
400
+ if (!$this->_getGravityHelper()->isFullyEnabled() || !$this->_getGravityHelper()->getCustomerUpdateEnabled()) {
401
+ return false;
402
+ }
403
+ try {
404
+
405
+ $customer = $observer->getCustomer();
406
+ if (!is_null($customer) && $customer->getId()) {
407
+
408
+ $parameters = array(
409
+ 'type' => Me_Gravity_Model_Method_Request::EVENT_TYPE_CUSTOMER_UPDATE
410
+ );
411
 
412
+ $exportModel = Mage::getModel('me_gravity/customers');
413
+ foreach ($exportModel->getExportHeaders() as $attribute) {
414
+ if ($attribute == 'userid') {
415
+ $parameters[$attribute] = $customer->getId();
416
+ } elseif ($attributeValue = $exportModel->getAttributeValueByCode($customer, $attribute)) {
417
+ $parameters[$attribute] = $attributeValue;
418
+ }
419
+ }
420
+
421
+ Mage::getModel('me_gravity/method_request')->sendRequest(
422
+ Me_Gravity_Model_Method_Request::EVENT_TYPE_UPDATE,
423
+ $parameters
424
+ );
425
+
426
+ }
427
+
428
+ } catch (Mage_Core_Exception $e) {
429
+ $this->_getGravityHelper()->getLogger($e->getMessage());
430
+ } catch (Exception $e) {
431
+ $this->_getGravityHelper()->getLogger(
432
+ $e->getMessage(),
433
+ $this->_getGravityHelper()->__('An error occurred while sending customer update event to Gravity.')
434
+ );
435
+ }
436
+
437
+ return $this;
438
+ }
439
  /**
440
  * Gravity product update event observer
441
  *
442
  * @param Varien_Event_Observer $observer observer
443
  * @return $this
444
  */
445
+
446
+
447
+ public function gravityProductDelete(Varien_Event_Observer $observer){
448
+
449
+ if (!$this->_getGravityHelper()->isFullyEnabled() || !$this->_getGravityHelper()->getProductUpdateEnabled()) {
450
  return false;
451
  }
452
+
453
+ try {
454
  $storeId = Mage::app()->getDefaultStoreView()->getId();
455
  $param = Mage::app()->getRequest()->getParam('store');
456
  if (isset($param) && $param) {
466
  'type' => Me_Gravity_Model_Method_Request::EVENT_TYPE_PRODUCT_UPDATE,
467
  'itemid' => $product->getId(),
468
  'title' => htmlspecialchars($product->getName()),
469
+ 'hidden' => true,
470
  'link' => $productUrl ? $productUrl : $product->getProductUrl(),
471
  'image_link' => htmlspecialchars($this->_getCatalogBaseMediaUrl() . $product->getImage()),
472
  'description' => htmlspecialchars($product->getDescription()),
498
  }
499
 
500
  return $this;
501
+
502
+ }
503
+ public function gravityProductUpdate(Varien_Event_Observer $observer)
504
+ {
505
+
506
+
507
+ if (!$this->_getGravityHelper()->isFullyEnabled() || !$this->_getGravityHelper()->getProductUpdateEnabled()) {
508
+ return false;
509
+ }
510
+
511
+ try {
512
+ $storeId = Mage::app()->getDefaultStoreView()->getId();
513
+ $param = Mage::app()->getRequest()->getParam('store');
514
+ if (isset($param) && $param) {
515
+ $storeId = $param;
516
+ }
517
+ $collection = Mage::getResourceModel('catalog/category_collection')
518
+ ->setStoreId($storeId)
519
+ ->addNameToResult();
520
+ $prod = $observer->getProduct();
521
+ $product = Mage::getModel('catalog/product')->load($prod->getId());
522
+ $hidden = ($product->getVisibility() == Mage_Catalog_Model_Product_Visibility::VISIBILITY_NOT_VISIBLE) ? 'true' : 'false';
523
+ if (!is_null($product) && $product->getId()) {
524
+ $cats = $product->getCategoryIds();
525
+ if(count($cats)==0){
526
+ $hidden = 'true';
527
+ }
528
+ $catPath = array();
529
+ foreach ($cats as $category_id) {
530
+ $_cat = Mage::getModel('catalog/category')->load($category_id) ;
531
+ $structure = preg_split('#/+#', $_cat->getPath());
532
+ for($j=0; $j<count($structure); $j=$j+1){
533
+ $structure[$j]=$collection->getItemById($structure[$j])->getName();
534
+ }
535
+ array_push($catPath, implode("/", $structure));
536
+ }
537
+ $baseUrl = Mage::app()->getStore($storeId)->getBaseUrl(Mage_Core_Model_Store::URL_TYPE_LINK);
538
+ $exportModel = Mage::getModel('me_gravity/products');
539
+ $productUrl = htmlspecialchars($baseUrl . $product->getUrlPath());
540
+ $parameters = array(
541
+ 'type' => Me_Gravity_Model_Method_Request::EVENT_TYPE_PRODUCT_UPDATE,
542
+ 'itemid' => $product->getId(),
543
+ 'title' => array(htmlspecialchars($product->getName())),
544
+ 'hidden' => $hidden,
545
+ 'URL' => array($productUrl ? $productUrl : $product->getProductUrl()),
546
+ 'Image' => array(htmlspecialchars($this->_getCatalogBaseMediaUrl() . $product->getImage())),
547
+ 'Price' => array($product->getFinalPrice()),
548
+ 'categoryPath' => $catPath,
549
+ 'categoryId' => $cats,
550
+ 'storeId' => array($storeId),
551
+ 'Description'=> array($product->getDescription())
552
+ );
553
+
554
+ $additionalParameters = $exportModel->getAdditionalAttributesXml($product, false, $storeId);
555
+ if ($additionalParameters) {
556
+ $parameters = array_merge($parameters, $additionalParameters);
557
+ }
558
+
559
+ Mage::getModel('me_gravity/method_request')->sendRequest(
560
+ Me_Gravity_Model_Method_Request::EVENT_TYPE_UPDATE,
561
+ $parameters
562
+ );
563
+
564
+ }
565
+
566
+ } catch (Mage_Core_Exception $e) {
567
+ $this->_getGravityHelper()->getLogger($e->getMessage());
568
+ } catch (Exception $e) {
569
+ $this->_getGravityHelper()->getLogger(
570
+ $e->getMessage(),
571
+ $this->_getGravityHelper()->__('An error occurred while sending product update event to Gravity.')
572
+ );
573
+ }
574
+
575
+ return $this;
576
  }
577
 
578
  /**
app/code/community/Me/Gravity/Model/System/Config/Source/Layout/Pages.php CHANGED
@@ -25,13 +25,16 @@ class Me_Gravity_Model_System_Config_Source_Layout_Pages
25
  $options = array();
26
 
27
  $_helper = $this->_getGravityHelper();
28
- $options[] = array('label' => '', 'value' => '');
29
- $options = array_merge($options, Mage::getSingleton('adminhtml/system_config_source_cms_page')->toOptionArray());
30
- $additionalOptions = array(
 
31
  array('value' => 'customer_account_index', 'label'=> $_helper->__('Account Dashboard')),
32
- array('value' => 'contacts_index_index', 'label'=> $_helper->__('Contact Us'))
 
 
 
33
  );
34
- $options = array_merge($options, $additionalOptions);
35
 
36
  return $options;
37
  }
25
  $options = array();
26
 
27
  $_helper = $this->_getGravityHelper();
28
+ // $options[] = array('label' => '', 'value' => '');
29
+ // $options = array_merge($options, Mage::getSingleton('adminhtml/system_config_source_cms_page')->toOptionArray());
30
+ $options = array(
31
+ array('value' => 'cms_index_index', 'label'=> $_helper->__('Home')),
32
  array('value' => 'customer_account_index', 'label'=> $_helper->__('Account Dashboard')),
33
+ array('value' => 'contacts_index_index', 'label'=> $_helper->__('Contact Us')),
34
+ array('value' => 'cms_index_noRoute', 'label'=> $_helper->__('404 Not Found'))
35
+
36
+
37
  );
 
38
 
39
  return $options;
40
  }
app/code/community/Me/Gravity/etc/config.xml CHANGED
@@ -12,7 +12,7 @@
12
  <config>
13
  <modules>
14
  <Me_Gravity>
15
- <version>1.0.2.1</version>
16
  </Me_Gravity>
17
  </modules>
18
  <global>
@@ -74,6 +74,14 @@
74
  </me_gravity_update_cart_after>
75
  </observers>
76
  </checkout_cart_update_items_before>
 
 
 
 
 
 
 
 
77
  <sales_order_place_after>
78
  <observers>
79
  <me_gravity_order_place_after>
@@ -129,6 +137,14 @@
129
  </me_gravity_customer_save_after>
130
  </observers>
131
  </customer_save_after>
 
 
 
 
 
 
 
 
132
  <catalog_product_save_after>
133
  <observers>
134
  <me_gravity_product_save_after>
@@ -137,6 +153,14 @@
137
  </me_gravity_product_save_after>
138
  </observers>
139
  </catalog_product_save_after>
 
 
 
 
 
 
 
 
140
  </events>
141
  </adminhtml>
142
  <crontab>
12
  <config>
13
  <modules>
14
  <Me_Gravity>
15
+ <version>1.1.0.0</version>
16
  </Me_Gravity>
17
  </modules>
18
  <global>
74
  </me_gravity_update_cart_after>
75
  </observers>
76
  </checkout_cart_update_items_before>
77
+ <customer_save_after>
78
+ <observers>
79
+ <me_gravity_customer_save>
80
+ <class>me_gravity/observer</class>
81
+ <method>gravityCustomerSave</method>
82
+ </me_gravity_customer_save>
83
+ </observers>
84
+ </customer_save_after>
85
  <sales_order_place_after>
86
  <observers>
87
  <me_gravity_order_place_after>
137
  </me_gravity_customer_save_after>
138
  </observers>
139
  </customer_save_after>
140
+ <catalog_product_delete_after>
141
+ <observers>
142
+ <me_gravity_product_delete_after>
143
+ <class>me_gravity/observer</class>
144
+ <method>gravityProductDelete</method>
145
+ </me_gravity_product_delete_after>
146
+ </observers>
147
+ </catalog_product_delete_after>
148
  <catalog_product_save_after>
149
  <observers>
150
  <me_gravity_product_save_after>
153
  </me_gravity_product_save_after>
154
  </observers>
155
  </catalog_product_save_after>
156
+ <catalog_product_save_before>
157
+ <observers>
158
+ <me_gravity_product_save_after>
159
+ <class>me_gravity/observer</class>
160
+ <method>gravityProductUpdate</method>
161
+ </me_gravity_product_save_after><!--új-->
162
+ </observers>
163
+ </catalog_product_save_before>
164
  </events>
165
  </adminhtml>
166
  <crontab>
app/code/community/Me/Gravity/etc/system.xml CHANGED
@@ -136,7 +136,7 @@
136
  </bulk>-->
137
  </fields>
138
  </config>
139
- <!-- <export translate="label">
140
  <label>Export Products</label>
141
  <frontend_type>text</frontend_type>
142
  <sort_order>20</sort_order>
@@ -921,7 +921,7 @@
921
  </top_box_columns>
922
  </fields>
923
  </category_display>
924
- <search_display translate="label">
925
  <label>Search Result Page Display</label>
926
  <frontend_type>text</frontend_type>
927
  <sort_order>70</sort_order>
@@ -995,7 +995,7 @@
995
  </depends>
996
  </search_box_columns>
997
  </fields>
998
- </search_display>
999
  <cart_display translate="label">
1000
  <label>Cart Page Display</label>
1001
  <frontend_type>text</frontend_type>
@@ -1078,7 +1078,7 @@
1078
  <show_in_website>1</show_in_website>
1079
  <show_in_store>1</show_in_store>
1080
  <fields>
1081
- <additional translate="label">
1082
  <label>Additional Attributes</label>
1083
  <frontend_type>multiselect</frontend_type>
1084
  <source_model>me_gravity/system_config_source_catalog_attributes</source_model>
@@ -1087,7 +1087,17 @@
1087
  <show_in_website>0</show_in_website>
1088
  <show_in_store>0</show_in_store>
1089
  <comment>Select additional attributes for catalog export.</comment>
1090
- </additional>
 
 
 
 
 
 
 
 
 
 
1091
  <only_salable translate="label">
1092
  <label>Only In-stock</label>
1093
  <frontend_type>select</frontend_type>
@@ -1160,7 +1170,7 @@
1160
  <enabled_js>1</enabled_js>
1161
  </depends>
1162
  </custom_js>
1163
- <template translate="label">
1164
  <label>Use Yusp Template</label>
1165
  <frontend_type>select</frontend_type>
1166
  <source_model>adminhtml/system_config_source_yesno</source_model>
@@ -1169,7 +1179,7 @@
1169
  <show_in_website>1</show_in_website>
1170
  <show_in_store>1</show_in_store>
1171
  <comment>General display setting. If switched to YES, all boxes will use a Yusp template.</comment>
1172
- </template>
1173
  <bulk translate="label">
1174
  <label>Enable Bulk Recommendation</label>
1175
  <frontend_type>select</frontend_type>
136
  </bulk>-->
137
  </fields>
138
  </config>
139
+ <!-- <export translate="label">
140
  <label>Export Products</label>
141
  <frontend_type>text</frontend_type>
142
  <sort_order>20</sort_order>
921
  </top_box_columns>
922
  </fields>
923
  </category_display>
924
+ <!-- <search_display translate="label">
925
  <label>Search Result Page Display</label>
926
  <frontend_type>text</frontend_type>
927
  <sort_order>70</sort_order>
995
  </depends>
996
  </search_box_columns>
997
  </fields>
998
+ </search_display>-->
999
  <cart_display translate="label">
1000
  <label>Cart Page Display</label>
1001
  <frontend_type>text</frontend_type>
1078
  <show_in_website>1</show_in_website>
1079
  <show_in_store>1</show_in_store>
1080
  <fields>
1081
+ <!--<additional translate="label">
1082
  <label>Additional Attributes</label>
1083
  <frontend_type>multiselect</frontend_type>
1084
  <source_model>me_gravity/system_config_source_catalog_attributes</source_model>
1087
  <show_in_website>0</show_in_website>
1088
  <show_in_store>0</show_in_store>
1089
  <comment>Select additional attributes for catalog export.</comment>
1090
+ </additional>-->
1091
+ <resynch translate="label">
1092
+ <label>Synchronization</label>
1093
+ <frontend_type>button</frontend_type>
1094
+ <frontend_model>me_gravity/adminhtml_system_config_form_synch</frontend_model>
1095
+ <sort_order>60</sort_order>
1096
+ <show_in_default>1</show_in_default>
1097
+ <show_in_website>1</show_in_website>
1098
+ <show_in_store>1</show_in_store>
1099
+ <comment>Every user and product item will be exported or updated in your database.</comment>
1100
+ </resynch>
1101
  <only_salable translate="label">
1102
  <label>Only In-stock</label>
1103
  <frontend_type>select</frontend_type>
1170
  <enabled_js>1</enabled_js>
1171
  </depends>
1172
  </custom_js>
1173
+ <!-- <template translate="label">
1174
  <label>Use Yusp Template</label>
1175
  <frontend_type>select</frontend_type>
1176
  <source_model>adminhtml/system_config_source_yesno</source_model>
1179
  <show_in_website>1</show_in_website>
1180
  <show_in_store>1</show_in_store>
1181
  <comment>General display setting. If switched to YES, all boxes will use a Yusp template.</comment>
1182
+ </template>-->
1183
  <bulk translate="label">
1184
  <label>Enable Bulk Recommendation</label>
1185
  <frontend_type>select</frontend_type>
app/design/adminhtml/default/default/template/me/gravity/system/config/form/GravityClient.php ADDED
@@ -0,0 +1,1124 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Gravity;
4
+ /**
5
+ * The GravityClient and related classes are used to connect to and communicate with the
6
+ * Gravity recommendation engine.
7
+ *
8
+ * @package GravityClient
9
+ */
10
+
11
+ /**
12
+ * The GravityClient class can be used to send events, item and user information to
13
+ * the recommendation engine and get recommendations.
14
+ *
15
+ * Example usage:
16
+ *
17
+ * <pre>
18
+ * function createGravityClient() {
19
+ * $config = new GravityClientConfig();
20
+ * $config->remoteUrl = 'https://<CUSTOMERID>-<SERVERLOCATION>.gravityrd-services.com/grrec-<CUSTOMERID>-war/WebshopServlet';
21
+ * $config->user = 'sampleUser';
22
+ * $config->password = 'samplePasswd';
23
+ * $config->retry = 0;
24
+ * return new GravityClient($config);
25
+ * }
26
+ * $client = createGravityClient();
27
+ * $context = new GravityRecommendationContext();
28
+ * $context->numberLimit = 5;
29
+ * $context->scenarioId = 'HOMEPAGE_MAIN';
30
+ * $context->nameValues = array(
31
+ * new GravityNameValue('minPrice', '100'),
32
+ * );
33
+ * $client->getItemRecommendation('user1', '123456789abcdef', $context);
34
+ * </pre>
35
+ *
36
+ * Please do not modify the GravityClient.php file (e.g. do not write your configuration parameters into the GravityClient.php file).
37
+ * Using an unmodified client makes version updates easier.
38
+ * Use your own factory function (like createGravityClient in the example above) to pass your configuration information to the GravityClient constructor.
39
+ *
40
+ */
41
+
42
+ class GravityClient {
43
+
44
+ /**
45
+ * The version info of the client.
46
+ */
47
+ public $version = '1.0.13';
48
+
49
+ /**
50
+ * Creates a new client instance with the specified configuration
51
+ * @param GravityClientConfig <var>$config</var> The configuration
52
+ */
53
+ public function __construct(GravityClientConfig $config) {
54
+ if ($config->timeoutSeconds <= 0) {
55
+ throw new GravityException(
56
+ 'Invalid configuration. Timeout must be a positive integer.',
57
+ new GravityFaultInfo(GRAVITY_ERRORCODE_CONFIG_ERROR));
58
+ }
59
+ if (!$config->remoteUrl) {
60
+ throw new GravityException(
61
+ 'Invalid configuration. Remote URL must be specified.',
62
+ new GravityFaultInfo(GRAVITY_ERRORCODE_CONFIG_ERROR));
63
+ }
64
+ $this->config = $config;
65
+ }
66
+
67
+ /**
68
+ * Adds an event to the recommendation engine.
69
+ *
70
+ * @param GravityEvent <var>$event</var> The event to add.
71
+ * @param boolean <var>$async</var> true if the call is asynchronous. An asynchronous call
72
+ * returns immediately after an input data checking,
73
+ * a synchronous call returns only after the data is saved to database.
74
+ */
75
+ public function addEvent(GravityEvent $event, $async) {
76
+ $this->addEvents(array($event), $async);
77
+ }
78
+
79
+ /**
80
+ * Adds multiple events to the recommendation engine.
81
+ *
82
+ * @param GravityEvent[] <var>$events</var> The events to add.
83
+ * @param boolean <var>$async</var> true if the call is asynchronous. An asynchronous call
84
+ * returns immediately after an input data checking,
85
+ * a synchronous call returns only after the data is saved to database.
86
+ */
87
+ public function addEvents(array $events, $async) {
88
+ $this->sendRequest('addEvents', array('async' => $async), $events, false);
89
+ }
90
+
91
+ /**
92
+ * Adds an item to the recommendation engine.
93
+ * If the item already exists with the specified itemId,
94
+ * the entire item along with its NameValue pairs will be replaced to the new item specified here.
95
+ *
96
+ * @param GravityItem <var>$item</var> The item to add
97
+ * @param boolean <var>$async</var> true if the call is asynchronous. An asynchronous call
98
+ * returns immediately after an input data checking,
99
+ * a synchronous call returns only after the data is saved to database.
100
+ */
101
+ public function addItem(GravityItem $item, $async) {
102
+ $this->addItems(array($item), $async);
103
+ }
104
+
105
+ /**
106
+ * Adds items to the recommendation engine.
107
+ * If an item already exists with the specified itemId,
108
+ * the entire item along with its NameValue pairs will be replaced to the new item specified here.
109
+ *
110
+ * @param GravityItem[] <var>$items</var> The items to add
111
+ * @param boolean <var>$async</var> true if the call is asynchronous. An asynchronous call
112
+ * returns immediately after an input data checking,
113
+ * a synchronous call returns only after the data is saved to database.
114
+ */
115
+ public function addItems(array $items, $async) {
116
+ $this->sendRequest('addItems', array('async' => $async), $items, false);
117
+ }
118
+
119
+ /**
120
+ * Existing item will be updated. If item does not exist Exception will be thrown.
121
+ * Update rules:
122
+ * - Key-value pairs won't be deleted only existing ones updated or new ones added. But If a key occurs in the key
123
+ * value list, then all values with the given key will be deleted and new values added in the recengine.
124
+ * - Hidden field has to be always specified!
125
+ *
126
+ * @param GravityItem $item The item to update
127
+ */
128
+ public function updateItem(GravityItem $item) {
129
+ $this->updateItems(array($item));
130
+ }
131
+
132
+ /**
133
+ * Existing items will be updated. If item does not exist Exception will be thrown.
134
+ * Update rules:
135
+ * - Key-value pairs won't be deleted only existing ones updated or new ones added. But If a key occurs in the key
136
+ * value list, then all values with the given key will be deleted and new values added in the recengine.
137
+ * - Hidden field has to be always specified!
138
+ *
139
+ * @param GravityItem[] $items The items to update
140
+ */
141
+ public function updateItems(array $items) {
142
+ $this->sendRequest('updateItems', NULL, $items, false);
143
+ }
144
+
145
+
146
+ /**
147
+ * Adds user to the recommendation engine.
148
+ * If the user already exists with the specified userId,
149
+ * the entire user will be replaced with the new user specified here.
150
+ *
151
+ * @param GravityUser <var>$user</var> The user to add.
152
+ * @param boolean <var>$async</var> true if the call is asynchronous. An asynchronous call
153
+ * returns immediately after an input data checking,
154
+ * a synchronous call returns only after the data is saved to database.
155
+ */
156
+ public function addUser(GravityUser $user, $async) {
157
+ $this->addUsers(array($user), $async);
158
+ }
159
+
160
+ /**
161
+ * Adds users to the recommendation engine. The existing users will be updated.
162
+ * If a user already exists with the specified userId,
163
+ * the entire user will be replaced with the new user specified here.
164
+ *
165
+ * @param GravityUser[] <var>$users</var> The users to add.
166
+ * @param boolean <var>$async</var> true if the call is asynchronous. An asynchronous call
167
+ * returns immediately after an input data checking,
168
+ * a synchronous call returns only after the data is saved to database.
169
+ */
170
+ public function addUsers(array $users, $async) {
171
+ $this->sendRequest('addUsers', array('async' => $async), $users, false);
172
+ }
173
+
174
+ /**
175
+ * Returns a list of recommended items, based on the given context parameters.
176
+ *
177
+ * @param string <var>$userId</var> The identifier of the logged in user. If no user is logged in, null should be specified.
178
+ * @param string <var>$cookieId</var> It should be a permanent identifier for the end users computer, preserving its value across browser sessions.
179
+ * It should be always specified.
180
+ * @param GravityRecommendationContext <var>$context</var>
181
+ * Additional information which describes the actual scenario.
182
+ * @return GravityItemRecommendation
183
+ * An object containing the recommended items and other information about the recommendation.
184
+ */
185
+ public function getItemRecommendation($userId, $cookieId, GravityRecommendationContext $context) {
186
+ return $this->sendRequest(
187
+ 'getItemRecommendation',
188
+ array(
189
+ 'userId' => $userId,
190
+ 'cookieId' => $cookieId,
191
+ ),
192
+ $context,
193
+ true
194
+ );
195
+ }
196
+
197
+ /**
198
+ * Given the userId and the cookieId, we can request recommendations for multiple scenarios (described by the context).
199
+ * This function returns lists of recommended items for each of the given scenarios in an array.
200
+ *
201
+ * @param string <var>$userId</var> The identifier of the logged in user. If no user is logged in, null should be specified.
202
+ * @param string <var>$cookieId</var> It should be a permanent identifier for the end users computer, preserving its value across browser sessions.
203
+ * It should be always specified.
204
+ * @param GravityRecommendationContext[] <var>$context</var>
205
+ * Additional Array of information which describes the actual scenarios.
206
+ * @return GravityItemRecommendation[]
207
+ * An Array containing the recommended items for each scenario with other information about the recommendation.
208
+ */
209
+ public function getItemRecommendationBulk($userId, $cookieId, array $context) {
210
+ foreach ($context as $element) {
211
+ $element->cookieId = $cookieId;
212
+ $element->userId = $userId;
213
+ }
214
+ return $this->sendRequest(
215
+ 'getItemRecommendationBulk',
216
+ array(
217
+ 'userId' => $userId,
218
+ 'cookieId' => $cookieId,
219
+ ),
220
+ $context,
221
+ true
222
+ );
223
+ }
224
+
225
+ /**
226
+ * Simple test function to test without side effects whether the service is alive.
227
+ * @return string "Hello " + <code>$name</code>
228
+ */
229
+ public function test($name) {
230
+ return $this->sendRequest('test', array('name' => $name), $name, true);
231
+ }
232
+
233
+ /**
234
+ * Simple test function to test throwing an exception.
235
+ */
236
+ public function testException() {
237
+ $this->sendRequest('testException', null, null, true);
238
+ }
239
+
240
+ private function getRequestQueryString($methodName, $queryStringParams) {
241
+ $queryString = $queryStringParams ? http_build_query($queryStringParams, null, '&') : '';
242
+ if ($queryString) {
243
+ $queryString = "&" . $queryString;
244
+ }
245
+ return "?method=" . urlencode($methodName) . $queryString . "&_v=" . urlencode($this->version);
246
+ }
247
+
248
+ private function sendRequestRetry($requestUrl, $requestBody, $isLast) {
249
+ $ch = curl_init();
250
+ curl_setopt($ch, CURLOPT_URL, $requestUrl);
251
+
252
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
253
+
254
+ if (is_int($this->config->timeoutSeconds)) {
255
+ curl_setopt($ch, CURLOPT_TIMEOUT, $this->config->timeoutSeconds);
256
+ curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $this->config->timeoutSeconds);
257
+ }
258
+ else {
259
+ curl_setopt($ch, CURLOPT_TIMEOUT_MS, $this->config->timeoutSeconds*1000);
260
+ curl_setopt($ch, CURLOPT_CONNECTTIMEOUT_MS, $this->config->timeoutSeconds*1000);
261
+ }
262
+
263
+ if (strpos($this->config->remoteUrl, 'https') === 0) {
264
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, $this->config->verifyPeer);
265
+ curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
266
+ }
267
+
268
+ if ($this->config->user) {
269
+ curl_setopt($ch, CURLOPT_USERPWD, $this->config->user . ':' . $this->config->password);
270
+ }
271
+
272
+ if ($requestBody) {
273
+ curl_setopt($ch, CURLOPT_POST, true);
274
+ curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($requestBody));
275
+ }
276
+
277
+ $header = array("X-Gravity-RecEng-ClientVersion: $this->version");
278
+ if ($this->config->forwardClientInfo) {
279
+ try {
280
+ if (array_key_exists('REMOTE_ADDR', $_SERVER)) {
281
+ $header[] = "X-Forwarded-For: ".$_SERVER['REMOTE_ADDR'];
282
+ }
283
+ if (array_key_exists('HTTP_REFERER', $_SERVER)) {
284
+ $header[] = "X-Original-Referer: ".$_SERVER['HTTP_REFERER'];
285
+ }
286
+ if (array_key_exists('HTTP_USER_AGENT', $_SERVER)) {
287
+ $header[] = "X-Device-User-Agent: ".$_SERVER['HTTP_USER_AGENT'];
288
+ curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
289
+ }
290
+ if (array_key_exists('HTTP_ACCEPT_LANGUAGE', $_SERVER)) {
291
+ $header[] = "X-Device-Accept-Language: ".$_SERVER['HTTP_ACCEPT_LANGUAGE'];
292
+ }
293
+ $originalRequestUri = $this->guessOriginalRequestURI();
294
+ if (!empty($originalRequestUri)) {
295
+ $header[] = "X-Original-RequestUri: ".$this->guessOriginalRequestURI();
296
+ } else {
297
+ // could not detect original request URI, send SAPI name for debugging purposes
298
+ $header[] = "X-PhpServerAPIName: ".php_sapi_name();
299
+ }
300
+ } catch (Exception $e) {
301
+ // FIXME: add error to the param list ...
302
+ }
303
+ }
304
+
305
+ // disable Expect: 100-Continue, it would cause an unnecessary roundtrip
306
+ // see http://www.w3.org/Protocols/rfc2616/rfc2616-sec8.html#sec8.2.3
307
+ $header[] = 'Expect:';
308
+
309
+ curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
310
+
311
+ $result = curl_exec($ch);
312
+ $err_code = curl_errno($ch);
313
+
314
+
315
+ if($isLast) {
316
+ $verbStr = '';
317
+ if($this->config->verbose) {
318
+ $hostname = "nan";
319
+ if(gethostname())
320
+ $hostname = gethostname();
321
+
322
+ $serverip = "nan";
323
+ if(array_key_exists('SERVER_ADDR', $_SERVER))
324
+ $serverip = $_SERVER['SERVER_ADDR'];
325
+
326
+ $curlinfo = curl_getinfo($ch);
327
+ $name_lookup_time = "nan";
328
+ if($curlinfo["namelookup_time"])
329
+ $name_lookup_time = $curlinfo["namelookup_time"];
330
+
331
+ $verbStr = "\nHOST: " .$hostname . "\nIP: " . $serverip . "\nlookup time: " . $name_lookup_time . "\nURL: " . $requestUrl . "\nBODY: " . print_r($requestBody, true) . "\n";
332
+ }
333
+ $rc = $this->handleError($ch, $result, $verbStr);
334
+ }
335
+ if (is_resource($ch)) {
336
+ curl_close($ch);
337
+ }
338
+
339
+ return array($err_code, $result);
340
+ }
341
+
342
+ private function sendRequest($methodName, $queryStringParams, $requestBody, $hasAnswer) {
343
+ $retry = 0;
344
+ if(isset($this->config->retry) && is_int($this->config->retry)) {
345
+ $retry = $this->config->retry;
346
+ }
347
+ if ($this->config->retryMethods) {
348
+ $retryEnabled = in_array($methodName, $this->config->retryMethods);
349
+ }
350
+ $isLast = !($retryEnabled && $retry > 0);
351
+
352
+ $requestUrl = $this->config->remoteUrl . "/" . $methodName . $this->getRequestQueryString($methodName, $queryStringParams);
353
+ $result_arr = $this->sendRequestRetry($requestUrl, $requestBody, $isLast);
354
+ $errnum = $result_arr[0];
355
+
356
+ while ($retryEnabled && $retry > 0 && $errnum != 0) {
357
+ $isLast = $retry <= 1;
358
+
359
+ $requestUrl = $requestUrl . "&_er=" . $errnum;
360
+ $result_arr = $this->sendRequestRetry($requestUrl, $requestBody, $isLast);
361
+ $errnum = $result_arr[0];
362
+
363
+ $retry--;
364
+ }
365
+
366
+ if ($hasAnswer) {
367
+ $result = $result_arr[1];
368
+ return json_decode($result, false);
369
+ } else {
370
+ return null;
371
+ }
372
+ }
373
+
374
+ private function handleError($ch, $result, $verbStr) {
375
+ $errorNumber = curl_errno($ch);
376
+ if ($errorNumber != 0) {
377
+ $errorMessage = curl_error($ch);
378
+ curl_close($ch);
379
+ switch ($errorNumber) {
380
+ case 6: //CURLE_COULDNT_RESOLVE_HOST
381
+ throw new GravityException(
382
+ "CURLE$errorNumber Could not resolve host error during curl_exec(): $errorMessage" . $verbStr,
383
+ new GravityFaultInfo(GRAVITY_ERRORCODE_COMM_HOSTRESOLVE));
384
+ case 7: //CURLE_COULDNT_CONNECT
385
+ throw new GravityException(
386
+ "CURLE$errorNumber Could not connect to host error during curl_exec(): $errorMessage" . $verbStr,
387
+ new GravityFaultInfo(GRAVITY_ERRORCODE_COMM_CONNECT));
388
+ case 28: //CURLE_OPERATION_TIMEDOUT
389
+ throw new GravityException(
390
+ "CURLE$errorNumber Timeout error during curl_exec(): $errorMessage" . $verbStr,
391
+ new GravityFaultInfo(GRAVITY_ERRORCODE_COMM_TIMEOUT));
392
+ default:
393
+ throw new GravityException(
394
+ "CURLE$errorNumber Error during curl_exec(): $errorMessage" . $verbStr,
395
+ new GravityFaultInfo(GRAVITY_ERRORCODE_COMM_OTHER));
396
+ }
397
+ } else {
398
+ $responseCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
399
+ if ($responseCode != 200) {
400
+ curl_close($ch);
401
+ $e = json_decode($result, false);
402
+ $supplement = "";
403
+ if (is_object($e)) {
404
+ $supplement = ", Message: $e->message" . $verbStr;
405
+ }
406
+ throw new GravityException(
407
+ "Non-200 HTTP response code: $responseCode $supplement",
408
+ new GravityFaultInfo(GRAVITY_ERRORCODE_COMM_HTTPERRORCODE));
409
+ }
410
+ return $responseCode;
411
+ }
412
+ }
413
+
414
+ private function guessOriginalRequestURI()
415
+ {
416
+ $sapi_name = php_sapi_name();
417
+ if ($sapi_name == 'cli') {
418
+ // using CLI PHP
419
+ return null;
420
+ }
421
+ $ssl = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ? true:false;
422
+ $sp = strtolower($_SERVER['SERVER_PROTOCOL']);
423
+ $protocol = substr($sp, 0, strpos($sp, '/')) . (($ssl) ? 's' : '');
424
+ $port = $_SERVER['SERVER_PORT'];
425
+ $port = ((!$ssl && $port=='80') || ($ssl && $port=='443')) ? '' : ':'.$port;
426
+ $host = isset($_SERVER['HTTP_X_FORWARDED_HOST']) ? $_SERVER['HTTP_X_FORWARDED_HOST'] : isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : $_SERVER['SERVER_NAME'];
427
+ $uri = $protocol . '://' . $host . $port . $_SERVER['REQUEST_URI'];
428
+ return $uri;
429
+ }
430
+ /**
431
+ * The client configuration.
432
+ *
433
+ * @var GravityClientConfig
434
+ */
435
+ private $config;
436
+ }
437
+
438
+
439
+ /**
440
+ * Contains a list of recommended items. This class is here only to describe the result,
441
+ * the actual result will not be an instance of this class because of json deserialization.
442
+ */
443
+ class GravityItemRecommendation {
444
+ function __construct() {
445
+ }
446
+
447
+ /**
448
+ *
449
+ * Array containing the recommended items.
450
+ * This is populated only if the scenario specifies to do so, otherwise this is null.
451
+ * itemIds is always populated.
452
+ * The items in this list only have the NameValues specified by the scenario.
453
+ * The list of NameValues specified by the scenario can be overridden by the
454
+ * GravityRecommendationContext resultNameValues on a per request basis.
455
+ *
456
+ * @var GravityItem[]
457
+ */
458
+ public $items;
459
+
460
+ /**
461
+ *
462
+ * The identifiers of the recommended items. Only if not a NameValue recommendation.
463
+ *
464
+ * @var int
465
+ */
466
+ public $itemIds;
467
+
468
+ /**
469
+ *
470
+ * The unique identifier of the recommendation generated by the recommendation engine.
471
+ * Strings in the PHP client are always UTF-8 encoded.
472
+ *
473
+ * @var string
474
+ */
475
+ public $recommendationId;
476
+
477
+ /**
478
+ * Array containing additional name-value pairs for recommendations.
479
+ * e.g.: AllItemCount for paging responses.
480
+ *
481
+ * @var GravityNameValue[]
482
+ */
483
+ public $outputNameValues;
484
+ }
485
+
486
+ /**
487
+ * Describes an event for the recommendation engine, for example a user viewed an item.
488
+ */
489
+ class GravityEvent {
490
+ function __construct() {
491
+ $this->time = time();
492
+ $this->nameValues = array();
493
+ }
494
+
495
+ /**
496
+ *
497
+ * The event type determines the namevalues which can be passed.
498
+ * <p>Possible list event types, which can be expanded based on what can the external system support:</p>
499
+ * <table border="1">
500
+ * <tr><th><code>Event Type</code><th>Category</th></th><th>Description</th><th>NameValues for the event</th></tr>
501
+ * <tr><td><code>VIEW</code></td><td>GENERAL</td><td>The user viewed the info page of an item.</td><td></td></tr>
502
+ * <tr><td><code>BUY</code></td><td>GENERAL</td><td>The user bought an item.</td><td>
503
+ * <table>
504
+ * <tr><td><code>OrderId</code></td><td></td></tr>
505
+ * <tr><td><code>UnitPrice</code></td><td>Formatted as a decimal number, for example 1234 or 12345.67</td></tr>
506
+ * <tr><td><code>Currency</code></td><td></td></tr>
507
+ * <tr><td><code>Quantity</code></td><td>Formatted as a decimal number.</td></tr>
508
+ * </table>
509
+ * </td></tr>
510
+ * <tr><td><code>RATING</code></td><td>GENERAL</td><td>The user rated an item.</td><td>
511
+ * <table>
512
+ * <tr><td><code>Value</code></td><td>The value of the rating.</td></tr>
513
+ * </table>
514
+ * </td></tr>
515
+ * <tr><td><code>ADD_TO_CART</code></td><td>GENERAL</td><td>The user added an item to the shopping cart.</td><td>
516
+ * <table>
517
+ * <tr><td><code>Quantity</code></td><td></td></tr>
518
+ * </table>
519
+ * </td></tr>
520
+ * <tr><td><code>REMOVE_FROM_CART</code></td><td>GENERAL</td><td>The user removed an item from the shopping cart.</td><td>
521
+ * <table>
522
+ * <tr><td><code>Quantity</code></td><td></td></tr>
523
+ * </table>
524
+ * </td></tr>
525
+ * <tr><td><code>ADD_TO_FAVORITES</code></td><td>GENERAL</td><td>The user added the item to his favorites.</td><td>
526
+ * <table>
527
+ * <tr><td><code>ListId</code></td><td>Use if the webshop supports multiple favorites lists.</td></tr>
528
+ * </table>
529
+ * </td></tr>
530
+ * <tr><td><code>REMOVE_FROM_FAVORITES</code></td><td>GENERAL</td><td>The user removed an item from his favorites.</td><td>
531
+ * <table>
532
+ * <tr><td><code>ListId</code></td><td>Use if the webshop supports multiple favorites lists.</td></tr>
533
+ * </table>
534
+ * </td></tr>
535
+ * <tr><td><code>REC_CLICK</code></td><td>GENERAL</td><td>The user clicked on a recommended item.</td><td>
536
+ * <table>
537
+ * <tr><td><code>Position</code></td><td>The position of the clicked item in the recommendation list. The position of the first item is 1.</td></tr>
538
+ * </table>
539
+ * </td></tr>
540
+ * <tr><td><code>LOGIN</code></td><td>GENERAL</td><td>The user logged in to the site. For this event the cookieId and also the userId must be specified.</td><td></td></tr>
541
+ * <tr><td><code>ADD_TO_WISHLIST</code></td><td>ADDITIONAL</td><td>The user added the item to his wishlist.</td><td>
542
+ * <table>
543
+ * <tr><td><code>ListId</code></td><td>Use if the webshop supports multiple wishlists.</td></tr>
544
+ * </table>
545
+ * </td></tr>
546
+ * <tr><td><code>REMOVE_FROM_WISHLIST</code></td><td>ADDITIONAL</td><td>The user removed an item from his wishlist.</td><td>
547
+ * <table>
548
+ * <tr><td><code>ListId</code></td><td>Use if the webshop supports multiple wishlists.</td></tr>
549
+ * </table>
550
+ * </td></tr>
551
+ * <tr><td><code>HIDE_PRODUCT</code></td><td>ADDITIONAL</td><td>The user hides a product that should not be recommended to him.</td><td></td></tr>
552
+ * <tr><td><code>UNHIDE_PRODUCT</code></td><td>ADDITIONAL</td><td>The user unhides a product that he marked as hidden previously.</td><td></td></tr>
553
+ * <tr><td><code>PRODUCT_SEARCH</code></td><td>ADDITIONAL</td><td>A list of products was displayed to the user, for example by browsing a category or by free text search.</td><td>
554
+ * <table>
555
+ * <tr><td><code>SearchString</code></td><td>The search string, if the list is based on a free text search.</td></tr>
556
+ * <tr><td><code>Filter.*</code></td><td>If the listing is based on comparing an item namevalue to a filter value, you can provide the actual filter here.
557
+ * For example, if the user was browsing a specific category, name='Filter.CategoryId' and value='CategoryA' can be specified.</td></tr>
558
+ * </table>
559
+ * </td></tr>
560
+ * <tr><td><code>NEXT_RECOMMENDATION</code></td><td>ADDITIONAL</td><td>The user asked for more recommendation.</td><td></td></tr>
561
+ * <tr><td><code>COMMENT</code></td><td>ADDITIONAL</td><td>The user wrote a comment for the item.</td><td></td></tr>
562
+ * <tr><td><code>NOT_INTERESTED</code></td><td>ADDITIONAL</td><td>The user would not like this item and similar items to be recommended to him, but he also does not want to give a negative rating for this item.</td><td></td></tr>
563
+ * <tr><td><code>LETTER_READ</code></td><td>ADDITIONAL</td><td>T The user read a letter which sent for him by the system (eg. a newsletter).</td><td></td></tr>
564
+ * <tr><td><code>CLICK_OUT</code></td><td>PRICE COMPARISON</td><td>The user jumps to an external webshop to buy the product. Used by price comparison sites.</td><td></td></tr>
565
+ * <tr><td><code>LANCE</code></td><td>AUCTION</td><td>The user place a bid on the item.</td><td><code>Value</code>The value of the bid as a decimal number.</td></tr>
566
+ * <tr><td><code>LETTER_SEND</code></td><td>AUCTION, ADVERTISING</td><td>The user sent a message to the advertiser.</td><td></td></tr>
567
+ * <tr><td><code>ADD_ITEM</code></td><td>AUCTION, ADVERTISING</td><td>The user added an item to the site.</td><td></td></tr>
568
+ * <tr><td><code>FREE_VIEW</code></td><td>MEDIA</td><td>The user wached/listened an item for free.</td><td><code>Duration</code>How long the user wached the item in seconds as a decimal number.</td></tr>
569
+ * <tr><td><code>PAID_VIEW</code></td><td>MEDIA</td><td>The user payed for waching/listening an item.</td><td>
570
+ * <table>
571
+ * <tr><td><code>Duration</code></td><td>How long the user wached the item in seconds. A decimal number.</td></tr>
572
+ * <tr><td><code>Value</code></td><td>How much the user payed for waching the item. A decimal number.</td></tr>
573
+ * </table>
574
+ * </td></tr>
575
+ * <tr><td><code>SUBSCRIPTION_VIEW</code></td><td>MEDIA</td><td>The user watched an item that was available for him by a subscription.</td><td>
576
+ * <table>
577
+ * <tr><td><code>Duration</code></td><td>How long the user wached the item in seconds. A decimal number.</td></tr>
578
+ * </table>
579
+ * </td></tr>
580
+ * <tr><td><code>FOLLOW_USER</code></td><td>SOCIAL</td><td>The user follows an other user.</td><td><code>OtherUserId</code>The identifier of the followed user.</td></tr>
581
+ * <tr><td><code>SHARE</code></td><td>SOCIAL</td><td>The user share the item on a social site (eg. Facebook, Twitter,...).</td><td></td></tr>
582
+ * <tr><td><code>REDEEM</code></td><td>COUPON</td><td>The user redeem the item (eg. a coupon).</td><td></td></tr>
583
+ * </table>
584
+ *
585
+ * @var string
586
+ */
587
+ public $eventType;
588
+
589
+ /**
590
+ *
591
+ * This is the identifier of the item which was viewed/bought/etc. by the user.
592
+ * Set to null if it does no make sense, for example in case of a login event.
593
+ * Strings in the PHP client are always UTF-8 encoded.
594
+ *
595
+ * @var string
596
+ */
597
+ public $itemId;
598
+
599
+ /**
600
+ *
601
+ * It should be an id of a previous recommendation, if this event is a consequence of a recommendation.
602
+ * Strings in the PHP client are always UTF-8 encoded.
603
+ *
604
+ * @var string
605
+ */
606
+ public $recommendationId;
607
+
608
+ /**
609
+ *
610
+ * The UNIX timestamp of the event, as returned by the standard time() PHP function.
611
+ *
612
+ * @var int
613
+ */
614
+ public $time;
615
+
616
+ /**
617
+ *
618
+ * This is the identifier of the user who generated the event.
619
+ * If unknown set to null (for example if the user is not logged in yet).
620
+ * Strings in the PHP client are always UTF-8 encoded.
621
+ *
622
+ * @var string
623
+ */
624
+ public $userId;
625
+
626
+ /**
627
+ *
628
+ * A cookieId should be a permanent identifier for the end users computer, preserving its value across browser sessions.
629
+ * This way not logged in users can be recognized, if they have logged in previously from the same computer.
630
+ * The cookieId should be always specified.
631
+ * Strings in the PHP client are always UTF-8 encoded.
632
+ *
633
+ * @var string
634
+ */
635
+ public $cookieId;
636
+
637
+ /**
638
+ *
639
+ * The NameValues for the event. The possible list of namevalues depends on the event type.
640
+ * NameValues provide additional description of the event.
641
+ * There can multiple NameValues with the same name.
642
+ * The order of NameValues will not be preserved, but the order of the values for the same name will be preserved.
643
+ *
644
+ * @var GravityNameValue[]
645
+ */
646
+ public $nameValues;
647
+ }
648
+
649
+ /**
650
+ * A user in the recommendation system. A user is an entity which generates event, and can get recommendations.
651
+ */
652
+ class GravityUser {
653
+ function __construct() {
654
+ $this->nameValues = array();
655
+ }
656
+
657
+ /**
658
+ *
659
+ * This is a unqiue identifier for a registered user.
660
+ * Strings in the PHP client are always UTF-8 encoded.
661
+ *
662
+ * @var string
663
+ */
664
+ public $userId;
665
+
666
+ /**
667
+ *
668
+ * NameValues provide additional description of the user.
669
+ * There can multiple NameValues with the same name.
670
+ * The order of NameValues will not be preserved.
671
+ *
672
+ * The recommendation engine in most cases does not require detailed information about the users, usually only some basic information can be used to enhance the quality of recommendation.
673
+ * For example:
674
+ * <table border="1">
675
+ * <tr><th>Name</th><th>Description</th></tr>
676
+ * <tr><td>ZipCode</td><td>The zip code of the user.</td></tr>
677
+ * <tr><td>City</td><td>The city of the user.</td></tr>
678
+ * <tr><td>Country</td><td>The country of the user.</td></tr>
679
+ * </table>
680
+ *
681
+ * @var GravityNameValue[]
682
+ */
683
+ public $nameValues;
684
+
685
+ /**
686
+ *
687
+ * True if the user is hidden. A no more existing user should be set to hidden.
688
+ *
689
+ * @var boolean
690
+ */
691
+ public $hidden;
692
+ }
693
+
694
+ /**
695
+ * An item is something that can be recommended to users.
696
+ */
697
+ class GravityItem {
698
+ function __construct() {
699
+ $this->fromDate = 0;
700
+ $this->toDate = 2147483647;
701
+ $this->nameValues = array();
702
+ }
703
+
704
+ /**
705
+ *
706
+ * The itemId is a unique identifier of the item.
707
+ * Strings in the PHP client are always UTF-8 encoded.
708
+ *
709
+ * @var string
710
+ */
711
+ public $itemId;
712
+
713
+ /**
714
+ * The item title. This is a short, human-readable name of the item.
715
+ * If the title is available in multiple languages, try to use your system's primary language, for example English.
716
+ * Strings in the PHP client are always UTF-8 encoded.
717
+ *
718
+ * @var string
719
+ */
720
+ public $title;
721
+
722
+ /**
723
+ *
724
+ * The type of the item. It can be used to create different item families.
725
+ * The purpose of itemtype is to differentiate items which will have different namevalue properties.
726
+ * Examples:
727
+ * <ul>
728
+ * <li>Book</li>
729
+ * <li>Ticket</li>
730
+ * <li>Computer</li>
731
+ * <li>Food</li>
732
+ * </ul>
733
+ *
734
+ * @var string
735
+ */
736
+ public $itemType;
737
+
738
+ /**
739
+ * The value of hidden. A hidden item will be never recommended.
740
+ *
741
+ * @var boolean
742
+ */
743
+ public $hidden;
744
+
745
+ /**
746
+ *
747
+ * An item is never recommended before this date.
748
+ * The date in unixtime format, the number of seconds elapsed since 1970.01.01 00:00:00 UTC, as returned by the standard time() PHP function.
749
+ * Set it to 0 if not important.
750
+ *
751
+ * @var int
752
+ */
753
+ public $fromDate;
754
+
755
+ /**
756
+ *
757
+ * An item is never recommended after this date.
758
+ * The date in unixtime format, the number of seconds elapsed since 1970.01.01 00:00:00 UTC, as returned by the standard time() PHP function.
759
+ * Set it to a big number (eg. 2147483647) if not important.
760
+ *
761
+ * @var int
762
+ */
763
+ public $toDate;
764
+
765
+
766
+ /**
767
+ *
768
+ * The NameValues for the item.
769
+ * <p>NameValues provide additional description of the item.</p>
770
+ * <p>There can multiple NameValues with the same name.</p>
771
+ * <p>The order of NameValues among different names will not be preserved, but the order of the values for the same name will be preserved.</p>
772
+ * <p>The recommendation engine can be configured to use some properties to create a relation between items.</p>
773
+ * <p>A possible list of names:</p>
774
+ * <table border="1">
775
+ * <tr><th>Name</th><th>Localizable</th><th>Description</th></tr>
776
+ * <tr><td>Title</td><td>Yes</td><td>The title of the item.</td></tr>
777
+ * <tr><td>Description</td><td>Yes</td><td>The description of item.</td></tr>
778
+ * <tr><td>CategoryPath</td><td>No</td><td>The full path of the item's category.
779
+ * For example, CategoryPath might be "books/computers/databases" for a book about databases.
780
+ * CategoryPath can be repeated if an item belongs to multiple categories. Use "/" only for separating levels.
781
+ * Later it is possible to use the recommendation engine to filter the list of items based on category, so it can provide recommendations for "Computer Books" category or only for "Computer Books &gt; Database" category.
782
+ * </td></tr>
783
+ * <tr><td>Tags</td><td>No</td><td>Tags for the item. Specify a separate namevalue for each tag.</td></tr>
784
+ * <tr><td>State</td><td>No</td><td>The state of the item, for example 'available', 'out of stock' etc.</td></tr>
785
+ * <tr><td>Price</td><td>No</td><td>The price of the item.</td></tr>
786
+ * </table>
787
+ *
788
+ * The recommendation engine can accept arbitrary namevalues, the list above is just an example of basic properties that are used almost everywhere.
789
+ * The NameValues which are relevant to business rules and possible content based filtering should be provided to the recommendation engine.
790
+ *
791
+ * <p>You can use localization by appending a language identifier to the Name of the NameValue. For example, Title_EN, Title_HU.
792
+ * It is possible to use both non-localized and localized version.
793
+ * </p>
794
+ *
795
+ * @var GravityNameValue[]
796
+ */
797
+ public $nameValues;
798
+
799
+ }
800
+
801
+ /**
802
+ * Contains information for a recommendation request.
803
+ */
804
+ class GravityRecommendationContext {
805
+ function __construct() {
806
+ $this->recommendationTime = time();
807
+ }
808
+
809
+ /**
810
+ *
811
+ * The time of the recommendation (seconds in unixtime format), the time when it will be shown to the end user.
812
+ * Use a value as returned by the standard time() PHP function.
813
+ *
814
+ * @var int
815
+ */
816
+ public $recommendationTime;
817
+
818
+ /**
819
+ *
820
+ * The value of the maximum number of items in the result.
821
+ * The maximum number of the items in the result can be also limited by the configuration of the scenario.
822
+ * If set to 0, this number of items is determined by the scenario.
823
+ *
824
+ * @var int
825
+ */
826
+ public $numberLimit;
827
+
828
+ /**
829
+ *
830
+ * The value of scenarioId. Scenarios are defined by the scenario management API.
831
+ * A scenario describes a way how recommended items will be filtered, ordered.
832
+ *
833
+ * @var string
834
+ */
835
+ public $scenarioId;
836
+
837
+ /**
838
+ *
839
+ * The NameValues for the context.
840
+ * NameValues can describe the parameters for the actual scenario, like current item id, filtering by category etc.
841
+ * Item-to-item recommendation is possible by a specific scenario which parses a NameValue describing the current item,
842
+ * or multiple NameValues if there are multiple actual items.
843
+ * The list of allowed names depends on the actual scenario.
844
+ * <p>The scenario can also specify that the result is not a list of items, but a list of values of item NameValues.</p>
845
+
846
+ * <table border="1">
847
+ * <tr><th>Name</th><th>Description</th></tr>
848
+ * <tr><td>CurrentItemId</td><td>The identifier of the actual item, if the current page is an item page.</td></tr>
849
+ * <tr><td>ItemOnPage</td><td>Identifier of item displayed elsewhere on the page. They will be excluded from recommendation. This namevalue can be used multiple times to provide a list of items.</td></tr>
850
+ * <tr><td>CartItemId</td><td>Identifier of item in the current shopping cart. This can provide additional information to improve the quality of recommendation. This namevalue must be used as many times as many items the shopping cart contains.</td></tr>
851
+ * <tr><td>CartItemQuantity</td><td>The quantity of items in the current shopping cart, in the same order as CartItemId namevalues.</td></tr>
852
+ * <tr><td>Filter.*</td><td>If specified, only items having the specified name and value as metadata will be in the result.
853
+ * For example, the namevalue with name='Filter'.'CategoryId' and value='A' means that only items belonging to category 'A' will be in the result.</td></tr>
854
+ *
855
+ * </table>
856
+ *
857
+ * @var GravityNameValue[]
858
+ */
859
+ public $nameValues;
860
+
861
+ /**
862
+ * If not null, specifies which NameValues of the recommended items should be included in the result.
863
+ * If null, the returned NameValues are determined by the actual scenario.
864
+ *
865
+ * @var GravityNameValue[]
866
+ */
867
+ public $resultNameValues;
868
+
869
+ }
870
+
871
+
872
+ /**
873
+ * A name and a value. This can be used to provide information about items, users and events.
874
+ */
875
+ class GravityNameValue {
876
+ /**
877
+ *
878
+ * The name.
879
+ * Strings in the PHP client are always UTF-8 encoded.
880
+ *
881
+ * @var string
882
+ */
883
+ public $name;
884
+
885
+ /**
886
+ *
887
+ * The value.
888
+ * Strings in the PHP client are always UTF-8 encoded.
889
+ *
890
+ * @var string
891
+ */
892
+ public $value;
893
+
894
+ /**
895
+ * Creates a new instance of a namevalue pair.
896
+ * Strings in the PHP client are always UTF-8 encoded.
897
+ *
898
+ * @param string <var>$name</var> The name.
899
+ * @param string <var>$value</var> The value.
900
+ */
901
+ public function __construct($name, $value) {
902
+ $this->name = $name;
903
+ $this->value = $value;
904
+ }
905
+ }
906
+
907
+
908
+
909
+ class GravityClientConfig {
910
+ function __construct() {
911
+ $this->timeoutSeconds = 2;
912
+ $this->verifyPeer = true;
913
+ $this->retryMethods = array("addUsers", "addItems", "addEvents", "getItemRecommendation");
914
+ $this->retry = 0;
915
+ $this->verbose = true;
916
+ $this->forwardClientInfo = true;
917
+ }
918
+
919
+ /**
920
+ * Forwards the user-agent, referrer, browser language and client IP to the recommendation engine.
921
+ * Default value is true;
922
+ *
923
+ * @var boolean
924
+ */
925
+ public $forwardClientInfo;
926
+
927
+ /**
928
+ * The URL of the server side interface. It has no default value, must be specified.
929
+ * Strings in the PHP client are always UTF-8 encoded.
930
+ *
931
+ * @var string
932
+ */
933
+ public $remoteUrl;
934
+
935
+ /**
936
+ * The timeout for the operations in seconds. The default value is 3 seconds.
937
+ * Double values are supported after PHP version 5.2.3 (uses miliseconds timeout)
938
+ * @var int
939
+ */
940
+ public $timeoutSeconds;
941
+
942
+ /**
943
+ * The setting of cURL option <code>CURLOPT_SSL_VERIFYPEER</code> in case of https connection.
944
+ * Set it to <code>false</code> if your server could not accept our certificate.
945
+ * The default value is true.
946
+ * Leave it blank in case of http connection.
947
+ *
948
+ * @var boolean
949
+ */
950
+ public $verifyPeer;
951
+
952
+ /**
953
+ *
954
+ * The user name for the http authenticated connection. Leave it blank in case of
955
+ * connection without authentication.
956
+ *
957
+ * @var string
958
+ */
959
+ public $user;
960
+
961
+ /**
962
+ * The password for the http authenticated connection. Leave it blank in case of
963
+ * connection without authentication.
964
+ *
965
+ * @var string
966
+ */
967
+ public $password;
968
+
969
+ /**
970
+ * The list of method names which should be retried after communication error.
971
+ *
972
+ * @var array(string)
973
+ */
974
+ public $retryMethods;
975
+
976
+ /**
977
+ * More verbose error messages in case of error.
978
+ *
979
+ * @var boolean
980
+ */
981
+ public $verbose;
982
+
983
+ /**
984
+ * If > 1 enables retry for the methods specified in $retryMethods.
985
+ *
986
+ * @var int
987
+ */
988
+ public $retry;
989
+ }
990
+
991
+ /**
992
+ * The client was initilized with invalid configuration.
993
+ * You should never use the value of the constant, always use it be referencing its name.
994
+ */
995
+ define('GRAVITY_ERRORCODE_CONFIG_ERROR', -1);
996
+
997
+ /**
998
+ * Unknown error during communication.
999
+ * You should never use the value of the constant, always use it be referencing its name.
1000
+ */
1001
+ define('GRAVITY_ERRORCODE_COMM_OTHER', -2);
1002
+
1003
+ /**
1004
+ * Could not resolve the remote host name.
1005
+ * You should never use the value of the constant, always use it be referencing its name.
1006
+ */
1007
+ define('GRAVITY_ERRORCODE_COMM_HOSTRESOLVE', -3);
1008
+
1009
+ /**
1010
+ * Timeout during communication.
1011
+ * You should never use the value of the constant, always use it be referencing its name.
1012
+ */
1013
+ define('GRAVITY_ERRORCODE_COMM_TIMEOUT', -4);
1014
+
1015
+ /**
1016
+ * Could not connect to remote host.
1017
+ * You should never use the value of the constant, always use it be referencing its name.
1018
+ */
1019
+ define('GRAVITY_ERRORCODE_COMM_CONNECT', -5);
1020
+
1021
+ /**
1022
+ * A non-200 HTTP response code was received.
1023
+ * You should never use the value of the constant, always use it be referencing its name.
1024
+ */
1025
+ define('GRAVITY_ERRORCODE_COMM_HTTPERRORCODE', -6);
1026
+
1027
+ /**
1028
+ * The exception class used by the recommendation engine client in case of an error.
1029
+ */
1030
+ class GravityException extends \Exception {
1031
+ /**
1032
+ * Creates a new instance of GravityException.
1033
+ *
1034
+ * @param string <var>$message</var> The error message.
1035
+ * @param GravityFaultInfo <var>$faultInfo</var> Contains information about the error.
1036
+ *
1037
+ */
1038
+ public function __construct($message, $faultInfo) {
1039
+ parent::__construct($message, $faultInfo->errorCode);
1040
+ $this->faultInfo = $faultInfo;
1041
+ }
1042
+
1043
+ /**
1044
+ * The object describing the error.
1045
+ *
1046
+ * @var GravityFaultInfo
1047
+ */
1048
+ public $faultInfo;
1049
+ }
1050
+
1051
+ /**
1052
+ * Describes the error occured during a request.
1053
+ */
1054
+ class GravityFaultInfo {
1055
+ function __construct($errorCode) {
1056
+ $this->errorCode = $errorCode;
1057
+ }
1058
+
1059
+ public $errorCode;
1060
+ }
1061
+
1062
+ /**
1063
+ * This class used to deserialize exceptions coming from the recommendation engine.
1064
+ */
1065
+ class GravityRecEngException {
1066
+
1067
+ public $message;
1068
+
1069
+ /**
1070
+ *
1071
+ * Currently defined error codes:
1072
+ * <ul>
1073
+ * <li>ERR_ITEMS_IS_NULL</li>
1074
+ * <li>ERR_ITEMS_HAS_NULL_ELEMENT</li>
1075
+ * <li>ERR_ITEMID_IS_NULL_OR_EMPTY</li>
1076
+ * <li>ERR_USERS_IS_NULL</li>
1077
+ * <li>ERR_USERS_HAS_NULL_ELEMENT</li>
1078
+ * <li>ERR_USERID_IS_NULL_OR_EMPTY</li>
1079
+ * <li>ERR_RATINGS_IS_NULL</li>
1080
+ * <li>ERR_RATINGS_HAS_NULL_ELEMENT</li>
1081
+ * <li>ERR_RECOMMENDATIONID_IS_NULL_OR_EMPTY</li>
1082
+ * <li>ERR_ITEM_NOT_FOUND</li>
1083
+ * <li>ERR_USER_NOT_FOUND</li>
1084
+ * <li>ERR_EVENTS_IS_NULL</li>
1085
+ * <li>ERR_EVENTS_HAS_NULL_ELEMENT</li>
1086
+ * <li>ERR_INVALID_EVENT_TYPE</li>
1087
+ * <li>ERR_PARAM_IS_NULL</li>
1088
+ * <li>ERR_NAMEVALUE_IS_NULL</li>
1089
+ * <li>ERR_NAME_IN_NAMEVALUE_IS_NULL_OR_EMPTY</li>
1090
+ * <li>ERR_VALUE_IN_NAMEVALUE_IS_NULL</li>
1091
+ * <li>ERR_NAME_IN_NAMEVALUE_IS_NOT_ALLOWED</li>
1092
+ * <li>ERR_ITEMID_INVALID_FROMTODATE</li>
1093
+ * <li>ERR_INVALID_EVENT_RECOMMENDATIONID</li>
1094
+ * <li>ERR_INTERNAL_ERROR</li>
1095
+ * <li>ERR_INVALID_METHOD_NAME</li>
1096
+ * </ul>
1097
+ *
1098
+ * @var string
1099
+ */
1100
+ public $faultInfo;
1101
+ }
1102
+
1103
+ class Message{
1104
+
1105
+ public function getMessage($errorcode){
1106
+
1107
+ switch($errorcode){
1108
+ case -1:
1109
+ return 'The client was initilized with invalid configuration.';
1110
+ case -2:
1111
+ return 'Unknown error during communication.';
1112
+ case -3:
1113
+ return 'Bad Webshop Servlet URL, please try again!<br>';
1114
+ case -4:
1115
+ return 'Timeout during communication.';
1116
+ case -5:
1117
+ return 'Could not connect to remote host.';
1118
+ case -6:
1119
+ return 'Bad customer id or password, please try again!<br>';
1120
+ default:
1121
+ return '';
1122
+ }
1123
+ }
1124
+ }
app/design/adminhtml/default/default/template/me/gravity/system/config/form/synch.phtml ADDED
@@ -0,0 +1,111 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ include("GravityClient.php");
4
+ use Magento\Framework\Event\ObserverInterface;
5
+ use Magento\Framework\Message\ManagerInterface as MessageManager;
6
+ use Gravity\GravityItem;
7
+ use Gravity\GravityClient;
8
+ use Gravity\GravityClientConfig;
9
+ use Gravity\GravityException;
10
+ use Gravity\GravityNameValue;
11
+ use Gravity\GravityUser;
12
+ use Gravity\Message;
13
+
14
+ function resync() {
15
+ $store =Mage::app()->getStore();
16
+ $baseUrl = Mage::app()->getStore()->getBaseUrl(Mage_Core_Model_Store::URL_TYPE_WEB);
17
+ $apiUser = Mage::getStoreConfig('gravity/config/api_user', $store);
18
+ $apiPassword = Mage::getStoreConfig('gravity/config/api_password', $store);
19
+ $apiUrl = Mage::getStoreConfig('gravity/config/api_url', $store);
20
+ $inStock = Mage::getStoreConfig('gravity/sync/only_salable', $store);
21
+ $config = new GravityClientConfig();
22
+ $config->user = $apiUser;
23
+ $config->remoteUrl = $apiUrl;
24
+ $config->password = $apiPassword;
25
+ $client = new GravityClient($config);
26
+ $products = Mage::getModel('catalog/product')->getCollection();
27
+ $collection = Mage::getResourceModel('catalog/category_collection')
28
+ ->setStoreId($store->getId())
29
+ ->addNameToResult();
30
+ $itemCollection = array();
31
+ foreach($products as $prod) {
32
+ $product = Mage::getModel('catalog/product')->load($prod->getId());
33
+ if($inStock==1 && $product->getStockItem()->getQty()<1){
34
+
35
+ }
36
+ elseif(count($product->getCategoryIds())==0){
37
+
38
+ }
39
+ else{
40
+ $item = new GravityItem();
41
+ $item->itemId = $product->getId();
42
+ $item->title = $product->getName();
43
+ if($product->getVisibility()==1){
44
+ $item->hidden = true;
45
+ }else {
46
+ $item->hidden=false;
47
+ }
48
+ $cats = $product->getCategoryIds();
49
+ $url =$baseUrl.$product->getUrlPath();
50
+ $imageUrl = Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_MEDIA).'catalog/product'.$product->getImage();
51
+ $item->nameValues = array(new GravityNameValue('Price', $product->getFinalPrice()),
52
+ new GravityNameValue('URL', $url),
53
+ new GravityNameValue('storeId', $store->getStoreId()),
54
+ new GravityNameValue('Image', $imageUrl),
55
+ new GravityNameValue('Description', $product->getDescription()));
56
+
57
+ foreach ($cats as $category_id) {
58
+
59
+ $_cat = Mage::getModel('catalog/category')->load($category_id) ;
60
+ $structure = preg_split('#/+#', $_cat->getPath());
61
+ for($j=0; $j<count($structure); $j=$j+1){
62
+ $structure[$j]=$collection->getItemById($structure[$j])->getName();
63
+ }
64
+ array_push($item->nameValues, new GravityNameValue('categoryPath', implode("/", $structure)));
65
+ array_push($item->nameValues, new GravityNameValue('categoryId', $category_id));
66
+ }
67
+
68
+ array_push($itemCollection, $item);
69
+ } }
70
+ $chunkedItems = array_chunk($itemCollection, 100);
71
+ $chunkedItemsNum = count($chunkedItems);
72
+ for($i=0; $i<$chunkedItemsNum; $i++){
73
+ try {
74
+ $client->addItems($chunkedItems[$i], true);
75
+ } catch (GravityException $e) {
76
+ }
77
+ }
78
+ $users = mage::getModel('customer/customer')->getCollection();
79
+ $gravityUserCollection = array();
80
+ foreach ($users as $user){
81
+ $user = Mage::getModel('customer/customer')->load($user->getId());
82
+ $gravityUser = new GravityUser();
83
+ $gravityUser->userId = $user->getId();
84
+ $gravityUser->hidden = false;
85
+ if($user->getGender()==1){
86
+ $gender = 'male';
87
+ }elseif($user->getGender()==2){
88
+ $gender = 'female';
89
+ }else{
90
+ $gender = 'not specified';
91
+ }
92
+ $gravityUser->nameValues = array(new GravityNameValue('name', $user->getName()),
93
+ new GravityNameValue('sex', $gender),
94
+ new GravityNameValue('email', $user->getEmail()));
95
+ array_push($gravityUserCollection, $gravityUser);
96
+ }
97
+ $chunkedUsers = array_chunk($gravityUserCollection, 100);
98
+ $chunkedUsersNum = count($chunkedUsers);
99
+ for($i=0; $i<$chunkedUsersNum; $i++){
100
+ try {
101
+ $client->addUsers($chunkedUsers[$i], true);
102
+ } catch (GravityException $e) {
103
+ }
104
+ }
105
+ }
106
+ if (isset($_GET['hello'])) {
107
+ resync();
108
+ }
109
+ ?>
110
+ <a href='index.php?hello=true'><input type="button" value="Export Catalog" class="form-button"/></a>
111
+
app/design/frontend/base/default/template/me/gravity/catalogsearch/js/gravity.phtml CHANGED
@@ -30,7 +30,7 @@
30
  type: "event",
31
  eventType: "SEARCH",
32
  storeId: <?php echo $this->getStoreId() ?>,
33
- searchKeyword: "<?php echo $this->getSearchKeyword() ?>",
34
  });
35
  //]]>
36
  </script>
30
  type: "event",
31
  eventType: "SEARCH",
32
  storeId: <?php echo $this->getStoreId() ?>,
33
+ searchExpression: "<?php echo $this->getSearchKeyword() ?>",
34
  });
35
  //]]>
36
  </script>
app/design/frontend/base/default/template/me/gravity/page/js/gravity.phtml CHANGED
@@ -18,6 +18,28 @@
18
  * @see Me_Gravity_Block_Page_Js_Gravity
19
  */
20
  ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
  <?php if ($this->isEnabled() && $this->getGravityCustomerId()) : ?>
22
  <?php $gravityHelper = $this->getGravityHelper(); ?>
23
  <?php if ($this->isCustomJsEnabled()) : ?>
18
  * @see Me_Gravity_Block_Page_Js_Gravity
19
  */
20
  ?>
21
+ <?php
22
+ $store =Mage::app()->getStore();
23
+ $collection = Mage::getResourceModel('catalog/category_collection')
24
+ ->setStoreId($store->getId())
25
+ ->addNameToResult();
26
+ $layer = Mage::getSingleton('catalog/layer');
27
+ if(isset($layer)){
28
+ $_category = $layer->getCurrentCategory();
29
+ $currentCategoryId= $_category->getId();
30
+ $_cat = Mage::getModel('catalog/category')->load($currentCategoryId);
31
+ $structure = preg_split('#/+#', $_cat->getPath());
32
+ for($j=0; $j<count($structure); $j=$j+1){
33
+ $structure[$j]=$collection->getItemById($structure[$j])->getName();
34
+ }
35
+ $currentCategoryPath = implode("/", $structure);
36
+
37
+ ?>
38
+ <script>
39
+ var _gravity = _gravity || [];
40
+ _gravity.push({type: 'set', categoryPath: '<?=$currentCategoryPath?>'});
41
+ </script>
42
+ <?php } ?>
43
  <?php if ($this->isEnabled() && $this->getGravityCustomerId()) : ?>
44
  <?php $gravityHelper = $this->getGravityHelper(); ?>
45
  <?php if ($this->isCustomJsEnabled()) : ?>
app/design/frontend/base/default/template/me/gravity/widget/boxes/widget.phtml CHANGED
@@ -15,6 +15,15 @@
15
  * @see Me_Gravity_Block_Widget_Boxes_Widget
16
  */
17
  ?>
 
 
 
 
 
 
 
 
 
18
  <?php $gravityHelper = $this->getGravityHelper(); ?>
19
  <?php if ($this->getTemplateType()) : ?>
20
  <?php $storeId = $this->getStoreId(); ?>
@@ -50,6 +59,7 @@
50
  type: "recommendation",
51
  scenarioId: "<?php echo $this->getRecommendationType() ?>",
52
  numberLimit: <?php echo $this->getRecommendationLimit() ?>,
 
53
  storeId: <?php echo $storeId ?>,
54
  resultNames: ["itemId", "title_<?php echo $storeId ?>", "link_<?php echo $storeId ?>", "image_link_<?php echo $storeId ?>"],
55
  templating: {
15
  * @see Me_Gravity_Block_Widget_Boxes_Widget
16
  */
17
  ?>
18
+ <?php
19
+ $layer = Mage::getSingleton('catalog/layer');
20
+ if(isset($layer)){
21
+ $_category = $layer->getCurrentCategory();
22
+ $currentCategoryId= $_category->getId();
23
+ }
24
+ else{
25
+ $currentCategoryId = '';
26
+ }?>
27
  <?php $gravityHelper = $this->getGravityHelper(); ?>
28
  <?php if ($this->getTemplateType()) : ?>
29
  <?php $storeId = $this->getStoreId(); ?>
59
  type: "recommendation",
60
  scenarioId: "<?php echo $this->getRecommendationType() ?>",
61
  numberLimit: <?php echo $this->getRecommendationLimit() ?>,
62
+ categoryId: "<?php echo $currentCategoryId ?>",
63
  storeId: <?php echo $storeId ?>,
64
  resultNames: ["itemId", "title_<?php echo $storeId ?>", "link_<?php echo $storeId ?>", "image_link_<?php echo $storeId ?>"],
65
  templating: {
package.xml CHANGED
@@ -1,7 +1,7 @@
1
  <?xml version="1.0"?>
2
  <package>
3
  <name>Me_Gravity</name>
4
- <version>1.1.0.1</version>
5
  <stability>stable</stability>
6
  <license uri="http://www.gravityrd.com/">Gravity R&amp;D, Ltd.</license>
7
  <channel>community</channel>
@@ -19,13 +19,13 @@ Yusp so the system can perform the analysis of customer behavior on the&#xD;
19
  site and calculate recommendations accordingly. With the extension, it&#xD;
20
  is also possible to export product catalogs and customers, or run daily&#xD;
21
  scheduled exports on cron jobs.</description>
22
- <notes>Version number: 1.1.0.1&#xD;
23
  Stability: Stable&#xD;
24
  Compatibility: CE 1.6.x, 1.7.x, 1.8.x, 1.9.x </notes>
25
  <authors><author><name>Gravity Recommendations</name><user>gravity_rd</user><email>web-integration@gravityrd.com</email></author></authors>
26
  <date>2016-10-15</date>
27
- <time>07:12:48</time>
28
- <contents><target name="mageetc"><dir name="modules"><file name="Me_Gravity.xml" hash="a385bf72a5c2f0f040d2bb0850ca0b7c"/></dir></target><target name="magecommunity"><dir name="Me"><dir name="Gravity"><dir name="Block"><file name="Abstract.php" hash="586409500493a209ba021f8d471c793c"/><dir name="Adminhtml"><dir name="System"><dir name="Config"><dir name="Form"><file name="Catalog.php" hash="6adcc355986762d7cc19f854c5fdd067"/><file name="Customer.php" hash="50336da73ad37e3895f82980387f6970"/><file name="Test.php" hash="07d7fce9dd15eb623918d6f01505cc32"/><file name="Version.php" hash="cdaa1bf4da1dffefb71aa3a27a63d2f1"/></dir></dir></dir></dir><dir name="Catalog"><dir name="Category"><dir name="Boxes"><file name="Category.php" hash="436b2d56c25114b152d786a939071cc4"/><file name="Personal.php" hash="7773ddf6e4a109e2cb16665ab1f469e6"/><file name="Top.php" hash="662641627445dd1a650467dfb2318151"/></dir></dir><dir name="Product"><dir name="View"><dir name="Boxes"><file name="Accessories.php" hash="765e6c65419b4c09702655d2e315835a"/><file name="Personal.php" hash="c3a1d8903982887485b1b0ca2c1548ec"/><file name="Product.php" hash="bc40a2d7e854fa9e6d8bb7b2bdd37a25"/><file name="Similar.php" hash="47099324fca5883edb881c8e4a3eb6bd"/></dir><dir name="Js"><file name="Gravity.php" hash="cba4e59a726e2ff10d746748731ac35e"/></dir></dir></dir></dir><dir name="Catalogsearch"><dir name="Advanced"><dir name="Js"><file name="Gravity.php" hash="a37130181b430d057fa2dcb76de0ff60"/></dir></dir><dir name="Boxes"><file name="Result.php" hash="1c59e5b53cbef273f6cb7cd3448aa45b"/></dir><dir name="Js"><file name="Gravity.php" hash="d065f4ef6555312988c2e165621ea2a8"/></dir></dir><dir name="Checkout"><dir name="Cart"><dir name="Boxes"><file name="Cart.php" hash="b720e576c5123f9d52ee98807cb7ac36"/></dir></dir></dir><dir name="General"><dir name="Boxes"><file name="Best.php" hash="07299f81cbf42d2fda4bfb31964f7c24"/><file name="History.php" hash="b50a5a27a6920efbf0ff51e349543e13"/><file name="Others.php" hash="263af4423f1dc40640c2bd0f3366cec5"/><file name="Popular.php" hash="d50fdf81725bd55be46141c5d5515480"/></dir></dir><dir name="Page"><dir name="Js"><file name="Gravity.php" hash="6f78a812fa42227b25780a483fd202d8"/></dir></dir><file name="Recommendation.php" hash="c0d131d38d35f18b596119c6c5253c13"/><dir name="Widget"><dir name="Boxes"><file name="Widget.php" hash="17560f25437bf04f2f8069b1aeee010e"/></dir></dir></dir><dir name="Helper"><file name="Boxes.php" hash="9d498b80819c6f8b5f94e77801e312ec"/><file name="Data.php" hash="4c17e76eee0b1216a707a7fed937ec2b"/></dir><dir name="Model"><dir name="Client"><file name="GravityClient.php" hash="361edf56f609ce392a748a7a91d718e6"/></dir><file name="Customers.php" hash="7399f7fb93965a3c67f5e2c941209ffe"/><dir name="Export"><file name="Abstract.php" hash="9f42701355b6bb288b4ead0eadcf19f0"/><dir name="Catalog"><file name="Product.php" hash="53e49c91d3ed270933d12251fc137a99"/></dir><dir name="Customer"><file name="Customer.php" hash="d3577acc08cd3004ccfb865232eebb9c"/></dir></dir><dir name="Method"><file name="Abstract.php" hash="c907e89db6238c5001cf653b31afa56e"/><file name="Request.php" hash="aa0c66be8bf119451e1a3560c7637fbc"/></dir><file name="Observer.php" hash="d268e4868b2223a0be9d7d7ad8a5c6bb"/><file name="Products.php" hash="3b76c51170818f04fe94606f85e09dd2"/><dir name="System"><dir name="Config"><dir name="Backend"><dir name="Catalog"><file name="Cron.php" hash="395fbd5f3d41223a336057b5bba6f4cc"/></dir></dir><dir name="Source"><dir name="Catalog"><file name="Attributes.php" hash="72df90bea6566c5e843c2301ba4dd6e1"/></dir><dir name="Customer"><file name="Attributes.php" hash="1e940ae61c568d83bc541b0fb8e87de1"/></dir><dir name="Layout"><file name="Layout.php" hash="18ab5c014f802bea1f6a841d062439ac"/><file name="Pages.php" hash="5e443f0c91329db385bc3d3b4e945c22"/></dir></dir></dir></dir></dir><dir name="controllers"><dir name="Adminhtml"><file name="GravityController.php" hash="c6237b4322d5a7a33d191789325b8036"/></dir></dir><dir name="etc"><file name="adminhtml.xml" hash="17bf0f5989e14d857252726fef4fad6d"/><file name="config.xml" hash="4fcbadbebe923abdb05794aab37475ba"/><file name="system.xml" hash="d061b368c41fdbb7320dac2e0fd3fba2"/><file name="system_backup.xml" hash="55672758af380c029374dadd629479b7"/><file name="widget.xml" hash="9662aa456d8dcf6b38503944427c247e"/></dir></dir></dir></target><target name="magedesign"><dir name="frontend"><dir name="base"><dir name="default"><dir name="template"><dir name="me"><dir name="gravity"><dir name="catalog"><dir name="category"><dir name="boxes"><file name="default.phtml" hash="f1569ed325e167d4e24b48101c109bed"/><file name="sidebar.phtml" hash="bfd9e6b741652779fea92b059f991822"/></dir></dir><dir name="product"><dir name="view"><dir name="boxes"><file name="default.phtml" hash="c916e1eeae7a719a2f284c19627eb50e"/><file name="sidebar.phtml" hash="c603cab98a672f113f0850ac850ee492"/></dir><dir name="js"><file name="gravity.phtml" hash="21b1752933f49d4fdf77c1dff3e8accb"/></dir></dir></dir></dir><dir name="catalogsearch"><dir name="advanced"><dir name="js"><file name="gravity.phtml" hash="ed37b5368abb0e5e1fddaf7d94f1634f"/></dir></dir><dir name="boxes"><file name="default.phtml" hash="600f331b3ef8772b652cc7fcde0270d6"/><file name="sidebar.phtml" hash="f9b64de7698f8d5a30da7dda56ef8f1d"/></dir><dir name="js"><file name="gravity.phtml" hash="a77756580b0a6577f9431194e88ce0f3"/></dir></dir><dir name="checkout"><dir name="cart"><dir name="boxes"><file name="default.phtml" hash="20aedc8eed8ab7e4c139f06cd6c0266f"/><file name="sidebar.phtml" hash="1b1f4c63788bfc9f9e338f664c50af64"/></dir></dir></dir><dir name="general"><dir name="boxes"><file name="default.phtml" hash="4b1308c89763c49b197883a9ae70e65b"/><file name="sidebar.phtml" hash="db426a25d29aaddf2c037aa471b0b855"/></dir></dir><dir name="page"><dir name="js"><file name="body-end.phtml" hash="c68cf0e1b26964c5867bd9fa1bf548c3"/><file name="gravity.phtml" hash="e092eaaf9062cd9028814239207129ff"/></dir></dir><dir name="widget"><dir name="boxes"><file name="widget.phtml" hash="80fd5994cde6c34f862e2850caa2beb1"/></dir></dir></dir></dir></dir><dir name="layout"><dir name="me"><file name="gravity.xml" hash="47f5ea1f53290cfd3f6a48bd2c64a7fc"/></dir></dir></dir></dir><dir name="rwd"><dir name="default"><dir name="template"><dir name="me"><dir name="gravity"><dir name="catalog"><dir name="category"><dir name="boxes"><file name="default.phtml" hash="4c4c9c68a8695e4ee0e8df9372e3e545"/><file name="sidebar.phtml" hash="7e7226aed80cd351b66e2b0c599608d5"/></dir></dir><dir name="product"><dir name="view"><dir name="boxes"><file name="default.phtml" hash="b68aa48c1e3ff9884884084660cb04cd"/><file name="sidebar.phtml" hash="3dfdc2dbdb9c69dbad73e93759fe6dee"/></dir></dir></dir></dir><dir name="catalogsearch"><dir name="boxes"><file name="default.phtml" hash="8dc241f668fad3b36e1a26d8c3b01802"/><file name="sidebar.phtml" hash="6aa688d961dfc9818001ae39866a4992"/></dir></dir><dir name="checkout"><dir name="cart"><dir name="boxes"><file name="default.phtml" hash="c81b3af4fe4fc03444da83f7416d0fc7"/><file name="sidebar.phtml" hash="d78a9160cbeded38e6a989eefe3c3753"/></dir></dir></dir><dir name="general"><dir name="boxes"><file name="default.phtml" hash="ec7412c0f1a6c8c15b859f5277c53885"/><file name="sidebar.phtml" hash="db426a25d29aaddf2c037aa471b0b855"/></dir></dir><dir name="widget"><dir name="boxes"><file name="widget.phtml" hash="41552aa04ba7810eada0706a8ee7f5ec"/></dir></dir></dir></dir></dir></dir></dir></dir><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="template"><dir name="me"><dir name="gravity"><dir name="system"><dir name="config"><dir name="form"><file name="test.phtml" hash="d9d972a23b04a34ab5f4d70a732d65b3"/></dir></dir></dir></dir></dir></dir></dir></dir></dir></target><target name="mageskin"><dir name="frontend"><dir name="base"><dir name="default"><dir name="css"><dir name="me"><dir name="gravity"><file name="gravity.css" hash="c2c4c7d30bced9a311c98032e38e0e11"/></dir></dir></dir></dir></dir></dir></target><target name="magelocal"><dir name="en_US"><file name="Me_Gravity.csv" hash=""/></dir></target></contents>
29
  <compatible/>
30
  <dependencies><required><php><min>5.3.0</min><max>5.6.15</max></php></required></dependencies>
31
  </package>
1
  <?xml version="1.0"?>
2
  <package>
3
  <name>Me_Gravity</name>
4
+ <version>1.1.0.2</version>
5
  <stability>stable</stability>
6
  <license uri="http://www.gravityrd.com/">Gravity R&amp;D, Ltd.</license>
7
  <channel>community</channel>
19
  site and calculate recommendations accordingly. With the extension, it&#xD;
20
  is also possible to export product catalogs and customers, or run daily&#xD;
21
  scheduled exports on cron jobs.</description>
22
+ <notes>Version number: 1.1.0.2&#xD;
23
  Stability: Stable&#xD;
24
  Compatibility: CE 1.6.x, 1.7.x, 1.8.x, 1.9.x </notes>
25
  <authors><author><name>Gravity Recommendations</name><user>gravity_rd</user><email>web-integration@gravityrd.com</email></author></authors>
26
  <date>2016-10-15</date>
27
+ <time>08:33:30</time>
28
+ <contents><target name="mageetc"><dir name="modules"><file name="Me_Gravity.xml" hash="a385bf72a5c2f0f040d2bb0850ca0b7c"/></dir></target><target name="magecommunity"><dir name="Me"><dir name="Gravity"><dir name="Block"><file name="Abstract.php" hash="586409500493a209ba021f8d471c793c"/><dir name="Adminhtml"><dir name="System"><dir name="Config"><dir name="Form"><file name="Catalog.php" hash="6adcc355986762d7cc19f854c5fdd067"/><file name="Customer.php" hash="50336da73ad37e3895f82980387f6970"/><file name="Synch.php" hash="c088bdb8abc2ca0411f6a8e905144d6b"/><file name="Test.php" hash="07d7fce9dd15eb623918d6f01505cc32"/><file name="Version.php" hash="cdaa1bf4da1dffefb71aa3a27a63d2f1"/></dir></dir></dir></dir><dir name="Catalog"><dir name="Category"><dir name="Boxes"><file name="Category.php" hash="436b2d56c25114b152d786a939071cc4"/><file name="Personal.php" hash="7773ddf6e4a109e2cb16665ab1f469e6"/><file name="Top.php" hash="662641627445dd1a650467dfb2318151"/></dir></dir><dir name="Product"><dir name="View"><dir name="Boxes"><file name="Accessories.php" hash="765e6c65419b4c09702655d2e315835a"/><file name="Personal.php" hash="c3a1d8903982887485b1b0ca2c1548ec"/><file name="Product.php" hash="bc40a2d7e854fa9e6d8bb7b2bdd37a25"/><file name="Similar.php" hash="47099324fca5883edb881c8e4a3eb6bd"/></dir><dir name="Js"><file name="Gravity.php" hash="cba4e59a726e2ff10d746748731ac35e"/></dir></dir></dir></dir><dir name="Catalogsearch"><dir name="Advanced"><dir name="Js"><file name="Gravity.php" hash="a37130181b430d057fa2dcb76de0ff60"/></dir></dir><dir name="Boxes"><file name="Result.php" hash="1c59e5b53cbef273f6cb7cd3448aa45b"/></dir><dir name="Js"><file name="Gravity.php" hash="d065f4ef6555312988c2e165621ea2a8"/></dir></dir><dir name="Checkout"><dir name="Cart"><dir name="Boxes"><file name="Cart.php" hash="b720e576c5123f9d52ee98807cb7ac36"/></dir></dir></dir><dir name="General"><dir name="Boxes"><file name="Best.php" hash="07299f81cbf42d2fda4bfb31964f7c24"/><file name="History.php" hash="b50a5a27a6920efbf0ff51e349543e13"/><file name="Others.php" hash="263af4423f1dc40640c2bd0f3366cec5"/><file name="Popular.php" hash="d50fdf81725bd55be46141c5d5515480"/></dir></dir><dir name="Page"><dir name="Js"><file name="Gravity.php" hash="6f78a812fa42227b25780a483fd202d8"/></dir></dir><file name="Recommendation.php" hash="c0d131d38d35f18b596119c6c5253c13"/><dir name="Widget"><dir name="Boxes"><file name="Widget.php" hash="17560f25437bf04f2f8069b1aeee010e"/></dir></dir></dir><dir name="Helper"><file name="Boxes.php" hash="9d498b80819c6f8b5f94e77801e312ec"/><file name="Data.php" hash="e4e59320874f84d6b928895eec36b106"/></dir><dir name="Model"><dir name="Client"><file name="GravityClient.php" hash="361edf56f609ce392a748a7a91d718e6"/></dir><file name="Customers.php" hash="7399f7fb93965a3c67f5e2c941209ffe"/><dir name="Export"><file name="Abstract.php" hash="9f42701355b6bb288b4ead0eadcf19f0"/><dir name="Catalog"><file name="Product.php" hash="2e6ffa32925cbf0ee110d17ca57e7ba8"/></dir><dir name="Customer"><file name="Customer.php" hash="d3577acc08cd3004ccfb865232eebb9c"/></dir></dir><dir name="Method"><file name="Abstract.php" hash="c907e89db6238c5001cf653b31afa56e"/><file name="Request.php" hash="31584c1e561651d0da15c0b0869cc3de"/></dir><file name="Observer.php" hash="216a6c6cab01c9c52254d3dcf396ec39"/><file name="Products.php" hash="3b76c51170818f04fe94606f85e09dd2"/><dir name="System"><dir name="Config"><dir name="Backend"><dir name="Catalog"><file name="Cron.php" hash="395fbd5f3d41223a336057b5bba6f4cc"/></dir></dir><dir name="Source"><dir name="Catalog"><file name="Attributes.php" hash="72df90bea6566c5e843c2301ba4dd6e1"/></dir><dir name="Customer"><file name="Attributes.php" hash="1e940ae61c568d83bc541b0fb8e87de1"/></dir><dir name="Layout"><file name="Layout.php" hash="18ab5c014f802bea1f6a841d062439ac"/><file name="Pages.php" hash="0eb22c10429bb136bd900b5b953887e5"/></dir></dir></dir></dir></dir><dir name="controllers"><dir name="Adminhtml"><file name="GravityController.php" hash="c6237b4322d5a7a33d191789325b8036"/></dir></dir><dir name="etc"><file name="adminhtml.xml" hash="17bf0f5989e14d857252726fef4fad6d"/><file name="config.xml" hash="22a061c8dd3d9ce6de4f72a5aa23f86a"/><file name="system.xml" hash="2a015e0bbf753f9ee96a7d324253d605"/><file name="system_backup.xml" hash="55672758af380c029374dadd629479b7"/><file name="widget.xml" hash="9662aa456d8dcf6b38503944427c247e"/></dir></dir></dir></target><target name="magedesign"><dir name="frontend"><dir name="base"><dir name="default"><dir name="template"><dir name="me"><dir name="gravity"><dir name="catalog"><dir name="category"><dir name="boxes"><file name="default.phtml" hash="f1569ed325e167d4e24b48101c109bed"/><file name="sidebar.phtml" hash="bfd9e6b741652779fea92b059f991822"/></dir></dir><dir name="product"><dir name="view"><dir name="boxes"><file name="default.phtml" hash="c916e1eeae7a719a2f284c19627eb50e"/><file name="sidebar.phtml" hash="c603cab98a672f113f0850ac850ee492"/></dir><dir name="js"><file name="gravity.phtml" hash="21b1752933f49d4fdf77c1dff3e8accb"/></dir></dir></dir></dir><dir name="catalogsearch"><dir name="advanced"><dir name="js"><file name="gravity.phtml" hash="ed37b5368abb0e5e1fddaf7d94f1634f"/></dir></dir><dir name="boxes"><file name="default.phtml" hash="600f331b3ef8772b652cc7fcde0270d6"/><file name="sidebar.phtml" hash="f9b64de7698f8d5a30da7dda56ef8f1d"/></dir><dir name="js"><file name="gravity.phtml" hash="64a5f0cd6f8e7098c744a7d3ea90961b"/></dir></dir><dir name="checkout"><dir name="cart"><dir name="boxes"><file name="default.phtml" hash="20aedc8eed8ab7e4c139f06cd6c0266f"/><file name="sidebar.phtml" hash="1b1f4c63788bfc9f9e338f664c50af64"/></dir></dir></dir><dir name="general"><dir name="boxes"><file name="default.phtml" hash="4b1308c89763c49b197883a9ae70e65b"/><file name="sidebar.phtml" hash="db426a25d29aaddf2c037aa471b0b855"/></dir></dir><dir name="page"><dir name="js"><file name="body-end.phtml" hash="c68cf0e1b26964c5867bd9fa1bf548c3"/><file name="gravity.phtml" hash="6aced3013b87635268b647cadd567aab"/></dir></dir><dir name="widget"><dir name="boxes"><file name="widget.phtml" hash="cbeca616b0b872437b1e52167ead0123"/></dir></dir></dir></dir></dir><dir name="layout"><dir name="me"><file name="gravity.xml" hash="47f5ea1f53290cfd3f6a48bd2c64a7fc"/></dir></dir></dir></dir><dir name="rwd"><dir name="default"><dir name="template"><dir name="me"><dir name="gravity"><dir name="catalog"><dir name="category"><dir name="boxes"><file name="default.phtml" hash="4c4c9c68a8695e4ee0e8df9372e3e545"/><file name="sidebar.phtml" hash="7e7226aed80cd351b66e2b0c599608d5"/></dir></dir><dir name="product"><dir name="view"><dir name="boxes"><file name="default.phtml" hash="b68aa48c1e3ff9884884084660cb04cd"/><file name="sidebar.phtml" hash="3dfdc2dbdb9c69dbad73e93759fe6dee"/></dir></dir></dir></dir><dir name="catalogsearch"><dir name="boxes"><file name="default.phtml" hash="8dc241f668fad3b36e1a26d8c3b01802"/><file name="sidebar.phtml" hash="6aa688d961dfc9818001ae39866a4992"/></dir></dir><dir name="checkout"><dir name="cart"><dir name="boxes"><file name="default.phtml" hash="c81b3af4fe4fc03444da83f7416d0fc7"/><file name="sidebar.phtml" hash="d78a9160cbeded38e6a989eefe3c3753"/></dir></dir></dir><dir name="general"><dir name="boxes"><file name="default.phtml" hash="ec7412c0f1a6c8c15b859f5277c53885"/><file name="sidebar.phtml" hash="db426a25d29aaddf2c037aa471b0b855"/></dir></dir><dir name="widget"><dir name="boxes"><file name="widget.phtml" hash="41552aa04ba7810eada0706a8ee7f5ec"/></dir></dir></dir></dir></dir></dir></dir></dir><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="template"><dir name="me"><dir name="gravity"><dir name="system"><dir name="config"><dir name="form"><file name="GravityClient.php" hash="15a4d36e2b697bf3e579fa3d0eb89c77"/><file name="synch.phtml" hash="dbd5e7f3a11b4f07c96cf0997c0bfa26"/><file name="test.phtml" hash="d9d972a23b04a34ab5f4d70a732d65b3"/></dir></dir></dir></dir></dir></dir></dir></dir></dir></target><target name="mageskin"><dir name="frontend"><dir name="base"><dir name="default"><dir name="css"><dir name="me"><dir name="gravity"><file name="gravity.css" hash="c2c4c7d30bced9a311c98032e38e0e11"/></dir></dir></dir></dir></dir></dir></target><target name="magelocal"><dir name="en_US"><file name="Me_Gravity.csv" hash="d41d8cd98f00b204e9800998ecf8427e"/></dir></target></contents>
29
  <compatible/>
30
  <dependencies><required><php><min>5.3.0</min><max>5.6.15</max></php></required></dependencies>
31
  </package>