LetsSyncroLLC_Oct8ne - Version 2.1.2

Version Notes

Currency and language support.
Added 2 new search engines: Solr , Celebros
Minor bugs fixed

Download this release

Release Info

Developer Oct8ne
Extension LetsSyncroLLC_Oct8ne
Version 2.1.2
Comparing to
See all releases


Code changes from version 2.1.1 to 2.1.2

Files changed (42) hide show
  1. app/code/community/LetsSyncroLLC/Oct8ne/Block/Accountconfig.php +26 -13
  2. app/code/community/LetsSyncroLLC/Oct8ne/Helper/Data.php +33 -29
  3. app/code/community/LetsSyncroLLC/Oct8ne/Helper/Image/Default.php +51 -13
  4. app/code/community/LetsSyncroLLC/Oct8ne/Helper/Image/Schuler.php +45 -37
  5. app/code/community/LetsSyncroLLC/Oct8ne/Helper/Search/Base.php +74 -3
  6. app/code/community/LetsSyncroLLC/Oct8ne/Helper/Search/Celebros.php +241 -0
  7. app/code/community/LetsSyncroLLC/Oct8ne/Helper/Search/CelebrosAPI/QwiserAnswer.php +30 -0
  8. app/code/community/LetsSyncroLLC/Oct8ne/Helper/Search/CelebrosAPI/QwiserAnswers.php +92 -0
  9. app/code/community/LetsSyncroLLC/Oct8ne/Helper/Search/CelebrosAPI/QwiserConcept.php +22 -0
  10. app/code/community/LetsSyncroLLC/Oct8ne/Helper/Search/CelebrosAPI/QwiserConcepts.php +24 -0
  11. app/code/community/LetsSyncroLLC/Oct8ne/Helper/Search/CelebrosAPI/QwiserProduct.php +37 -0
  12. app/code/community/LetsSyncroLLC/Oct8ne/Helper/Search/CelebrosAPI/QwiserProductAnswer.php +21 -0
  13. app/code/community/LetsSyncroLLC/Oct8ne/Helper/Search/CelebrosAPI/QwiserProductAnswers.php +22 -0
  14. app/code/community/LetsSyncroLLC/Oct8ne/Helper/Search/CelebrosAPI/QwiserProductField.php +17 -0
  15. app/code/community/LetsSyncroLLC/Oct8ne/Helper/Search/CelebrosAPI/QwiserProductFields.php +22 -0
  16. app/code/community/LetsSyncroLLC/Oct8ne/Helper/Search/CelebrosAPI/QwiserProducts.php +25 -0
  17. app/code/community/LetsSyncroLLC/Oct8ne/Helper/Search/CelebrosAPI/QwiserProductsMetaData.php +14 -0
  18. app/code/community/LetsSyncroLLC/Oct8ne/Helper/Search/CelebrosAPI/QwiserQuestion.php +30 -0
  19. app/code/community/LetsSyncroLLC/Oct8ne/Helper/Search/CelebrosAPI/QwiserQuestions.php +87 -0
  20. app/code/community/LetsSyncroLLC/Oct8ne/Helper/Search/CelebrosAPI/QwiserSearchAPI.php +428 -0
  21. app/code/community/LetsSyncroLLC/Oct8ne/Helper/Search/CelebrosAPI/QwiserSearchPath.php +23 -0
  22. app/code/community/LetsSyncroLLC/Oct8ne/Helper/Search/CelebrosAPI/QwiserSearchPathEntry.php +18 -0
  23. app/code/community/LetsSyncroLLC/Oct8ne/Helper/Search/CelebrosAPI/QwiserSearchResults.php +98 -0
  24. app/code/community/LetsSyncroLLC/Oct8ne/Helper/Search/CelebrosAPI/QwiserSpellerInformation.php +18 -0
  25. app/code/community/LetsSyncroLLC/Oct8ne/Helper/Search/CelebrosAPI/SearchInformation.php +44 -0
  26. app/code/community/LetsSyncroLLC/Oct8ne/Helper/Search/CelebrosAPI/SortingOptions.php +20 -0
  27. app/code/community/LetsSyncroLLC/Oct8ne/Helper/Search/CelebrosAPI/domxml-php4-to-php5.php +316 -0
  28. app/code/community/LetsSyncroLLC/Oct8ne/Helper/Search/Sli.php +18 -14
  29. app/code/community/LetsSyncroLLC/Oct8ne/Helper/Search/Solr.php +466 -0
  30. app/code/community/LetsSyncroLLC/Oct8ne/Helper/Version.php +1 -1
  31. app/code/community/LetsSyncroLLC/Oct8ne/Model/ImageWidth.php +22 -0
  32. app/code/community/LetsSyncroLLC/Oct8ne/Model/SearchEngines.php +3 -1
  33. app/code/community/LetsSyncroLLC/Oct8ne/controllers/FrameController.php +44 -33
  34. app/code/community/LetsSyncroLLC/Oct8ne/controllers/SetupController.php +49 -8
  35. app/code/community/LetsSyncroLLC/Oct8ne/etc/config.xml +4 -3
  36. app/code/community/LetsSyncroLLC/Oct8ne/etc/system.xml +34 -2
  37. app/code/community/LetsSyncroLLC/Oct8ne/sql/oct8ne_setup/mysql4-install-2.1.2.php +74 -0
  38. app/code/community/LetsSyncroLLC/Oct8ne/sql/oct8ne_setup/mysql4-upgrade-2.1.0-2.1.1.php +8 -0
  39. app/code/community/LetsSyncroLLC/Oct8ne/sql/oct8ne_setup/mysql4-upgrade-2.1.1-2.1.2.php +8 -0
  40. app/design/frontend/base/default/template/oct8ne/letssyncro.phtml +2 -2
  41. app/etc/modules/LetsSyncroLLC_Oct8ne.xml +1 -1
  42. package.xml +7 -6
app/code/community/LetsSyncroLLC/Oct8ne/Block/Accountconfig.php CHANGED
@@ -3,6 +3,7 @@
3
  class LetsSyncroLLC_Oct8ne_Block_Accountconfig extends Mage_Core_Block_Template {
4
 
5
  private $_html = '';
 
6
 
7
  protected function _toHtml() {
8
  $submitLetsSyncroCredentials = $this->getRequest()->getParam('submitLetsSyncroCredentials');
@@ -19,7 +20,11 @@ class LetsSyncroLLC_Oct8ne_Block_Accountconfig extends Mage_Core_Block_Template
19
  } elseif (empty($letssyncro_password)) {
20
  $this->_html .= '<div id="messagesbox"><ul class="messages"><li class="error-msg"><ul><li><div id="themessage">' . $this->__('The field (Password) cannot be empty.') . '</div></li></ul></li></ul><br></div>';
21
  } elseif (!$this->updateLetsSyncroUserPassword($letssyncrooptions, $letssyncromodel, $letssyncro_useremail, $letssyncro_password)) {
22
- $this->_html .= '<div id="messagesbox"><ul class="messages"><li class="error-msg"><ul><li><div id="themessage">' . $this->__('There was an error on your credentials and cannot obtain OCT8NE integration data.') . '</div></li></ul></li></ul><br></div>';
 
 
 
 
23
  } elseif (!$this->updateLetsSyncroEnabled('1', $letssyncrooptions, $letssyncromodel)) {
24
  $this->_html .= '<div id="messagesbox"><ul class="messages"><li class="error-msg"><ul><li><div id="themessage">' . $this->__('There was an error activating OCT8NE integration.') . '</div></li></ul></li></ul><br></div>';
25
  } else {
@@ -180,21 +185,19 @@ class LetsSyncroLLC_Oct8ne_Block_Accountconfig extends Mage_Core_Block_Template
180
 
181
  $xml = new SimpleXmlElement($response);
182
 
183
- if (!isset($xml->LicenseId)) {
 
 
184
  $letssyncromodel->setEnabled('0');
185
  return false;
186
  }
187
-
188
- if ($xml) {
189
- if ($letssyncromodel->setApitoken($xml->ApiToken) &&
190
- $letssyncromodel->setLicenseid($xml->LicenseId) &&
191
- $letssyncromodel->setEmail($letssyncro_useremail) &&
192
- $letssyncromodel->setPassword($letssyncro_password))
193
- return true;
194
- }
195
- else {
196
- return false;
197
  }
 
198
  } catch (Exception $e) {
199
  return false;
200
  }
@@ -203,11 +206,14 @@ class LetsSyncroLLC_Oct8ne_Block_Accountconfig extends Mage_Core_Block_Template
203
  }
204
 
205
  public function sendRequest($xmlData, $method = '', $letssyncro_url, $letssyncro_apitoken = '') {
 
 
206
  if ($method == 'logon')
207
  $letssyncro_url = $letssyncro_url . '/' . $method;
208
  else
209
  $letssyncro_url = $letssyncro_url . '/updateNodes?userid=' . $letssyncro_apitoken;
210
 
 
211
  if (function_exists('curl_init') == 1) {
212
  $ch = curl_init($letssyncro_url);
213
  curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
@@ -217,7 +223,14 @@ class LetsSyncroLLC_Oct8ne_Block_Accountconfig extends Mage_Core_Block_Template
217
  curl_setopt($ch, CURLOPT_POSTFIELDS, $xmlData);
218
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
219
  $response = curl_exec($ch);
220
- curl_close($ch);
 
 
 
 
 
 
 
221
  } else {
222
  $opts = array('http' =>
223
  array(
3
  class LetsSyncroLLC_Oct8ne_Block_Accountconfig extends Mage_Core_Block_Template {
4
 
5
  private $_html = '';
6
+ private $message = '';
7
 
8
  protected function _toHtml() {
9
  $submitLetsSyncroCredentials = $this->getRequest()->getParam('submitLetsSyncroCredentials');
20
  } elseif (empty($letssyncro_password)) {
21
  $this->_html .= '<div id="messagesbox"><ul class="messages"><li class="error-msg"><ul><li><div id="themessage">' . $this->__('The field (Password) cannot be empty.') . '</div></li></ul></li></ul><br></div>';
22
  } elseif (!$this->updateLetsSyncroUserPassword($letssyncrooptions, $letssyncromodel, $letssyncro_useremail, $letssyncro_password)) {
23
+ $msg = $this->message;
24
+ if (!$msg) {
25
+ $msg = $this->__('There was an error in your credentials and we could not get OCT8NE integration data.');
26
+ }
27
+ $this->_html .= '<div id="messagesbox"><ul class="messages"><li class="error-msg"><ul><li><div id="themessage">' . $msg . '</div></li></ul></li></ul><br></div>';
28
  } elseif (!$this->updateLetsSyncroEnabled('1', $letssyncrooptions, $letssyncromodel)) {
29
  $this->_html .= '<div id="messagesbox"><ul class="messages"><li class="error-msg"><ul><li><div id="themessage">' . $this->__('There was an error activating OCT8NE integration.') . '</div></li></ul></li></ul><br></div>';
30
  } else {
185
 
186
  $xml = new SimpleXmlElement($response);
187
 
188
+ $this->message = isset($xml->Message) ? $xml->Message : NULL;
189
+
190
+ if (!$xml || ("" . $xml->LicenseId === "")) {
191
  $letssyncromodel->setEnabled('0');
192
  return false;
193
  }
194
+ if ($letssyncromodel->setApitoken($xml->ApiToken) &&
195
+ $letssyncromodel->setLicenseid($xml->LicenseId) &&
196
+ $letssyncromodel->setEmail($letssyncro_useremail) &&
197
+ $letssyncromodel->setPassword($letssyncro_password)) {
198
+ return true;
 
 
 
 
 
199
  }
200
+ return false;
201
  } catch (Exception $e) {
202
  return false;
203
  }
206
  }
207
 
208
  public function sendRequest($xmlData, $method = '', $letssyncro_url, $letssyncro_apitoken = '') {
209
+ $urlWithoutHttps = str_replace("https://", "http://", $letssyncro_url);
210
+
211
  if ($method == 'logon')
212
  $letssyncro_url = $letssyncro_url . '/' . $method;
213
  else
214
  $letssyncro_url = $letssyncro_url . '/updateNodes?userid=' . $letssyncro_apitoken;
215
 
216
+
217
  if (function_exists('curl_init') == 1) {
218
  $ch = curl_init($letssyncro_url);
219
  curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
223
  curl_setopt($ch, CURLOPT_POSTFIELDS, $xmlData);
224
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
225
  $response = curl_exec($ch);
226
+ $error = curl_error($ch);
227
+ curl_close($ch);
228
+
229
+ if ($error && strpos(strtolower($error), 'ssl') !== false) {
230
+ if($urlWithoutHttps != $letssyncro_url) {
231
+ return $this->sendRequest($xmlData, $method, $urlWithoutHttps, $letssyncro_apitoken);
232
+ }
233
+ }
234
  } else {
235
  $opts = array('http' =>
236
  array(
app/code/community/LetsSyncroLLC/Oct8ne/Helper/Data.php CHANGED
@@ -33,8 +33,8 @@ class LetsSyncroLLC_Oct8ne_Helper_Data extends Mage_Core_Helper_Abstract {
33
  }
34
  return $result;
35
  }
36
-
37
- static public function getProductsInfoByIds($productIds, $qtyPerProduct = null) {
38
  if (empty($productIds)) {
39
  return array();
40
  }
@@ -44,13 +44,12 @@ class LetsSyncroLLC_Oct8ne_Helper_Data extends Mage_Core_Helper_Abstract {
44
  if (Mage::getStoreConfig('oct8neData/advancedDataConfig/loadCompleteProductInfo')) {
45
  $result = self::getFullProductsInfoByIds($productIds, $qtyPerProduct);
46
  } else {
47
- $result = self::getOptimizedProductsInfoByIds($productIds, $qtyPerProduct);
48
- }
49
  $profiler->endProfile($startTime, "[Data] Create product info");
50
  return $result;
51
  }
52
 
53
-
54
  static private function getFullProductsInfoByIds($productIds, $qtyPerProduct = null) {
55
  $result = array();
56
  foreach ($productIds as $id) {
@@ -107,21 +106,22 @@ class LetsSyncroLLC_Oct8ne_Helper_Data extends Mage_Core_Helper_Abstract {
107
 
108
  static public function createProductSummaryFromProduct($product, $qty = null) {
109
  $product_id = $product->getId();
110
- $prevPrice = Mage::helper('core')->currency($product->getPrice(), false, false);
111
- $finalPrice = Mage::helper('core')->currency($product->getFinalPrice(), false, false);
112
  $productUrl = self::_remove_http($product->getProductUrl());
113
  $thumbnail = self::_remove_http(self::getProductThumbnail($product, 120));
114
  $title = htmlspecialchars($product->getName(), ENT_QUOTES, "UTF-8");
 
115
 
116
  $result = array(
117
  'internalId' => $product_id,
118
  'title' => $title,
119
- 'prevPrice' => number_format($prevPrice, '2', '.', ','),
120
- 'price' => number_format($finalPrice, '2', '.', ','),
121
  'productUrl' => $productUrl,
122
  'thumbnail' => $thumbnail,
123
  );
124
- if($qty) {
125
  $result['qty'] = $qty;
126
  }
127
  return $result;
@@ -134,8 +134,12 @@ class LetsSyncroLLC_Oct8ne_Helper_Data extends Mage_Core_Helper_Abstract {
134
  $tmp = self::createProductSummaryFromProduct($product);
135
 
136
  $description = self::getSanitizedDescription($product);
 
 
 
 
137
  $useProductUrl = true;
138
- if (self::isSaleable($product)) {
139
  if (!self::productHasOptions($product)) {
140
  $useProductUrl = false;
141
  }
@@ -168,31 +172,31 @@ class LetsSyncroLLC_Oct8ne_Helper_Data extends Mage_Core_Helper_Abstract {
168
  return $result;
169
  }
170
 
171
- static private function isSaleable($product) {
172
 
173
  $stockItem = $product->getStockItem();
174
  if (!$stockItem) {
175
  $stockItem = Mage::getModel('cataloginventory/stock_item')->loadByProduct($product);
176
  }
177
 
178
- // If we are not managing stocks for this product, it is saleable.
179
- // If we are managing stocks for this product,
180
- // we consider it saleable if we have it in stock
181
- // or stock = 0 but we allow backorders (orders over without stock).
182
-
183
- if ($stockItem->getManageStock() > 0) {
184
- $stock = intval($stockItem->getQty());
185
- if ($stock > 0) {
186
- $saleable = true;
187
- } else if ($stockItem->getBackorders()) {
188
- $saleable = true;
189
- } else {
190
- $saleable = false;
 
 
191
  }
192
- } else {
193
- $saleable = true;
194
- }
195
- return $saleable;
196
  }
197
 
198
  static public function getRelatedProducts($productId, $page, $pageSize) {
33
  }
34
  return $result;
35
  }
36
+
37
+ static public function getProductsInfoByIds($productIds, $qtyPerProduct = null) {
38
  if (empty($productIds)) {
39
  return array();
40
  }
44
  if (Mage::getStoreConfig('oct8neData/advancedDataConfig/loadCompleteProductInfo')) {
45
  $result = self::getFullProductsInfoByIds($productIds, $qtyPerProduct);
46
  } else {
47
+ $result = self::getOptimizedProductsInfoByIds($productIds, $qtyPerProduct);
48
+ }
49
  $profiler->endProfile($startTime, "[Data] Create product info");
50
  return $result;
51
  }
52
 
 
53
  static private function getFullProductsInfoByIds($productIds, $qtyPerProduct = null) {
54
  $result = array();
55
  foreach ($productIds as $id) {
106
 
107
  static public function createProductSummaryFromProduct($product, $qty = null) {
108
  $product_id = $product->getId();
109
+ $formattedPrevPrice = $product->getFinalPrice() != 0 ? Mage::helper('core')->currency($product->getPrice(), true, false): NULL;
110
+ $formattedPrice = $product->getFinalPrice() != 0 ? Mage::helper('core')->currency($product->getFinalPrice(), true, false) : NULL;
111
  $productUrl = self::_remove_http($product->getProductUrl());
112
  $thumbnail = self::_remove_http(self::getProductThumbnail($product, 120));
113
  $title = htmlspecialchars($product->getName(), ENT_QUOTES, "UTF-8");
114
+
115
 
116
  $result = array(
117
  'internalId' => $product_id,
118
  'title' => $title,
119
+ 'formattedPrevPrice' => $formattedPrevPrice,
120
+ 'formattedPrice' => $formattedPrice,
121
  'productUrl' => $productUrl,
122
  'thumbnail' => $thumbnail,
123
  );
124
+ if ($qty) {
125
  $result['qty'] = $qty;
126
  }
127
  return $result;
134
  $tmp = self::createProductSummaryFromProduct($product);
135
 
136
  $description = self::getSanitizedDescription($product);
137
+
138
+ // useProductUrl must be
139
+ // false if the product has stock and the product has no attributes (not configurable)
140
+ // true if the product is out of stock or the product has attributes (configurable)
141
  $useProductUrl = true;
142
+ if (self::isStockAvailable($product)) {
143
  if (!self::productHasOptions($product)) {
144
  $useProductUrl = false;
145
  }
172
  return $result;
173
  }
174
 
175
+ static private function isStockAvailable($product) {
176
 
177
  $stockItem = $product->getStockItem();
178
  if (!$stockItem) {
179
  $stockItem = Mage::getModel('cataloginventory/stock_item')->loadByProduct($product);
180
  }
181
 
182
+ $available = true;
183
+ $productIsInStock = $stockItem->getIsInStock();
184
+ $productsCount = (float) $stockItem->getQty();
185
+ $minProductsAllowed = (float) $stockItem->getMinQty();
186
+ $backOrdersAllowed = $stockItem->getBackorders();
187
+ $magentoIsManagingStocks = $stockItem->getManageStock();
188
+ $ignoreBackorders = Mage::getStoreConfig('oct8neData/productData/ignoreBackorders');
189
+
190
+ if ($magentoIsManagingStocks) {
191
+ if (!$productIsInStock || $productsCount <= $minProductsAllowed) {
192
+ if ($ignoreBackorders) {
193
+ $available = false;
194
+ } else {
195
+ $available = $stockItem->getBackorders() ? true : false;
196
+ }
197
  }
198
+ }
199
+ return $available;
 
 
200
  }
201
 
202
  static public function getRelatedProducts($productId, $page, $pageSize) {
app/code/community/LetsSyncroLLC/Oct8ne/Helper/Image/Default.php CHANGED
@@ -28,7 +28,6 @@ class LetsSyncroLLC_Oct8ne_Helper_Image_Default extends Mage_Core_Helper_Url {
28
 
29
  $start = $profiler->startProfile();
30
 
31
- // Proof of concept: get valid images
32
  $images = $this->getValidImages($gallery_info, $product);
33
 
34
  $v = array();
@@ -71,24 +70,25 @@ class LetsSyncroLLC_Oct8ne_Helper_Image_Default extends Mage_Core_Helper_Url {
71
  $resizedImageUrl = Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_MEDIA) . DS . $this->getCachedProductDir($fileName, $width);
72
 
73
  // If the original image doesn`t exist, return the small placeholder
74
- if (!file_exists($originalImagePhysicalPath) && is_file($originalImagePhysicalPath)) {
75
  return $this->getPlaceholder($width, $height);
76
  }
77
 
78
  // If width is not specified, the image is returned "as is"
79
  if (!$width) {
80
- return $this->removeHttp($originalImageUrl);
81
  }
82
 
83
  // If the cached image already exists, return it
84
  if (file_exists($resizedImagePhysicalPath)) {
85
- return $this->removeHttp($resizedImageUrl);
86
  }
87
 
88
  // If the cached image if smaller than the width requested, return it
 
89
  $imageObj = new Varien_Image($originalImagePhysicalPath);
90
  if ($imageObj->getOriginalWidth() <= $width) {
91
- return $this->removeHttp($originalImageUrl);
92
  }
93
 
94
  // If we got this so far, resize and return the new image
@@ -98,9 +98,9 @@ class LetsSyncroLLC_Oct8ne_Helper_Image_Default extends Mage_Core_Helper_Url {
98
  $imageObj->keepTransparency(TRUE);
99
  $imageObj->resize($width, $height);
100
  $imageObj->save($resizedImagePhysicalPath);
101
- return $this->removeHttp($resizedImageUrl);
102
  }
103
-
104
  public function getImagePhysicalPath($fileName) {
105
  return Mage::getBaseDir(Mage_Core_Model_Store::URL_TYPE_MEDIA) . DS . $this->getProductDir($fileName);
106
  }
@@ -112,6 +112,7 @@ class LetsSyncroLLC_Oct8ne_Helper_Image_Default extends Mage_Core_Helper_Url {
112
  }
113
 
114
  protected function getFirstGalleryImage($product, $width) {
 
115
  $product->getResource()->getAttribute('media_gallery')
116
  ->getBackend()->afterLoad($product);
117
 
@@ -128,6 +129,25 @@ class LetsSyncroLLC_Oct8ne_Helper_Image_Default extends Mage_Core_Helper_Url {
128
  return $imageUrl;
129
  }
130
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
131
  protected function getProductDir($file) {
132
  return "catalog" . DS . "product" . DS . $file;
133
  }
@@ -147,7 +167,7 @@ class LetsSyncroLLC_Oct8ne_Helper_Image_Default extends Mage_Core_Helper_Url {
147
  return self::$profiler;
148
  }
149
 
150
- private function getThumbnail($product, $width, $imageType, $url) {
151
  if ($url == 'no_selection') {
152
  return NULL;
153
  }
@@ -159,7 +179,7 @@ class LetsSyncroLLC_Oct8ne_Helper_Image_Default extends Mage_Core_Helper_Url {
159
  return $file;
160
  }
161
 
162
- private function getParentThumbnail($product, $width) {
163
  if ($product->getTypeId() == "simple") {
164
  $parentIds = Mage::getModel('catalog/product_type_grouped')->getParentIdsByChild($product->getId());
165
  if (!$parentIds) {
@@ -174,13 +194,27 @@ class LetsSyncroLLC_Oct8ne_Helper_Image_Default extends Mage_Core_Helper_Url {
174
  return $imageUrl;
175
  }
176
 
 
 
 
 
 
 
 
 
 
 
 
 
177
  // Returns valid gallery images for a product.
178
  // If no image could be found:
179
  // - Try to return Image, Small_Image or Thumbnail (in that order)
180
  // - If still no images found, return the placeholder
181
 
182
- private function getValidImages($gallery, $product) {
183
  $mustIgnoreExcludedImages = Mage::getStoreConfig('oct8neData/productData/ignoreExcludedImages');
 
 
184
  $url = Mage::getUrl('oct8ne/frame/image');
185
  $join = (strstr($url, "?") === FALSE) ? '?' : '&';
186
  $result = array();
@@ -188,10 +222,14 @@ class LetsSyncroLLC_Oct8ne_Helper_Image_Default extends Mage_Core_Helper_Url {
188
  $isImageExcluded = $image['disabled'] == '1' || $image['disabled_default'] == '1';
189
  if (!$isImageExcluded || !$mustIgnoreExcludedImages) {
190
  $file = $image['file'];
191
- if (strpos($file, '/') !== 0) {
192
- $file = "/$file";
 
 
 
 
 
193
  }
194
- $result[] = $this->removeHttp($url) . $join . 'file=' . $file;
195
  }
196
  }
197
  if (empty($result)) {
28
 
29
  $start = $profiler->startProfile();
30
 
 
31
  $images = $this->getValidImages($gallery_info, $product);
32
 
33
  $v = array();
70
  $resizedImageUrl = Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_MEDIA) . DS . $this->getCachedProductDir($fileName, $width);
71
 
72
  // If the original image doesn`t exist, return the small placeholder
73
+ if (!is_file($originalImagePhysicalPath)) {
74
  return $this->getPlaceholder($width, $height);
75
  }
76
 
77
  // If width is not specified, the image is returned "as is"
78
  if (!$width) {
79
+ return $this->sanitizeUrl($this->removeHttp($originalImageUrl));
80
  }
81
 
82
  // If the cached image already exists, return it
83
  if (file_exists($resizedImagePhysicalPath)) {
84
+ return $this->sanitizeUrl($this->removeHttp($resizedImageUrl));
85
  }
86
 
87
  // If the cached image if smaller than the width requested, return it
88
+
89
  $imageObj = new Varien_Image($originalImagePhysicalPath);
90
  if ($imageObj->getOriginalWidth() <= $width) {
91
+ return $this->sanitizeUrl($this->removeHttp($originalImageUrl));
92
  }
93
 
94
  // If we got this so far, resize and return the new image
98
  $imageObj->keepTransparency(TRUE);
99
  $imageObj->resize($width, $height);
100
  $imageObj->save($resizedImagePhysicalPath);
101
+ return $this->sanitizeUrl($this->removeHttp($resizedImageUrl));
102
  }
103
+
104
  public function getImagePhysicalPath($fileName) {
105
  return Mage::getBaseDir(Mage_Core_Model_Store::URL_TYPE_MEDIA) . DS . $this->getProductDir($fileName);
106
  }
112
  }
113
 
114
  protected function getFirstGalleryImage($product, $width) {
115
+
116
  $product->getResource()->getAttribute('media_gallery')
117
  ->getBackend()->afterLoad($product);
118
 
129
  return $imageUrl;
130
  }
131
 
132
+ protected function sanitizeUrl($url) {
133
+ $url = str_replace("\\", "/", $url);
134
+ $prefix = "";
135
+
136
+ if (substr($url, 0, 7) == "http://") {
137
+ $prefix = "http:";
138
+ } else if (substr($url, 0, 8) == "https://") {
139
+ $prefix = "https://";
140
+ } else if (substr($url, 0, 2) == "//") {
141
+ $prefix = "//";
142
+ }
143
+ $path = $prefix == "" ? $url : substr($url, strlen($prefix));
144
+ while (strpos($path, "//") !== false) {
145
+ $path = str_replace("//", '/', $path);
146
+ }
147
+ $result = $prefix . $path;
148
+ return $result;
149
+ }
150
+
151
  protected function getProductDir($file) {
152
  return "catalog" . DS . "product" . DS . $file;
153
  }
167
  return self::$profiler;
168
  }
169
 
170
+ protected function getThumbnail($product, $width, $imageType, $url) {
171
  if ($url == 'no_selection') {
172
  return NULL;
173
  }
179
  return $file;
180
  }
181
 
182
+ protected function getParentThumbnail($product, $width) {
183
  if ($product->getTypeId() == "simple") {
184
  $parentIds = Mage::getModel('catalog/product_type_grouped')->getParentIdsByChild($product->getId());
185
  if (!$parentIds) {
194
  return $imageUrl;
195
  }
196
 
197
+ protected function getAbsoluteImageUrl($file, $width) {
198
+
199
+ if ($width) {
200
+ return $this->resizeImg($file, $width);
201
+ }
202
+
203
+ $file = ltrim($file, "/");
204
+ $file = Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_MEDIA) . $this->getProductDir($file);
205
+ $file = str_replace(DS, '/', $file);
206
+ return $this->removeHttp($file);
207
+ }
208
+
209
  // Returns valid gallery images for a product.
210
  // If no image could be found:
211
  // - Try to return Image, Small_Image or Thumbnail (in that order)
212
  // - If still no images found, return the placeholder
213
 
214
+ protected function getValidImages($gallery, $product) {
215
  $mustIgnoreExcludedImages = Mage::getStoreConfig('oct8neData/productData/ignoreExcludedImages');
216
+ $useProductActualImages = Mage::getStoreConfig('oct8neData/productData/returnActualProductImageUrl');
217
+ $actualProductImageWidth = Mage::getStoreConfig('oct8neData/productData/actualProductImageWidth');
218
  $url = Mage::getUrl('oct8ne/frame/image');
219
  $join = (strstr($url, "?") === FALSE) ? '?' : '&';
220
  $result = array();
222
  $isImageExcluded = $image['disabled'] == '1' || $image['disabled_default'] == '1';
223
  if (!$isImageExcluded || !$mustIgnoreExcludedImages) {
224
  $file = $image['file'];
225
+ if ($useProductActualImages) {
226
+ $result[] = $this->getAbsoluteImageUrl($file, $actualProductImageWidth);
227
+ } else {
228
+ if (strpos($file, '/') !== 0) {
229
+ $file = "/$file";
230
+ }
231
+ $result[] = $this->removeHttp($url) . $join . 'file=' . $file;
232
  }
 
233
  }
234
  }
235
  if (empty($result)) {
app/code/community/LetsSyncroLLC/Oct8ne/Helper/Image/Schuler.php CHANGED
@@ -2,42 +2,47 @@
2
 
3
  class LetsSyncroLLC_Oct8ne_Helper_Image_Schuler extends LetsSyncroLLC_Oct8ne_Helper_Image_Default {
4
 
5
- public function resizeImg($fileName, $width, $height = null) {
6
- if (!$fileName) {
7
- $width = $width ? $width : 120;
8
- $height = $height ? $height : $width;
9
- return $this->removeHttp(Mage::getModel('catalog/product')->getSmallImageUrl($width, $height));
10
- }
11
 
12
- $folderURL = Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_MEDIA) . DS . "catalog" . DS . "product" . DS;
13
- $imageURL = $folderURL . $fileName;
 
14
 
15
- $basePath = Mage::getBaseDir(Mage_Core_Model_Store::URL_TYPE_MEDIA) . DS . "catalog" . DS . "product" . DS . $fileName;
16
- $newPath = Mage::getBaseDir(Mage_Core_Model_Store::URL_TYPE_MEDIA) . DS . "catalog" . DS . "product" . DS . "cache" . DS . "resized" . DS . $width . DS . $fileName;
17
- //if width empty then return original size image's URL
18
- if ($width != '') {
19
- //if image has already resized then just return URL
20
- if (file_exists($basePath) && is_file($basePath) && !file_exists($newPath)) {
21
- $imageObj = new Varien_Image($basePath);
22
- if ($imageObj->getOriginalWidth() <= $width) {
23
- return $imageURL;
 
 
 
24
  }
25
- $imageObj->constrainOnly(TRUE);
26
- $imageObj->keepAspectRatio(FALSE);
27
- $imageObj->keepFrame(FALSE);
28
- $imageObj->keepTransparency(TRUE);
29
- $imageObj->resize($width, $height);
30
- $imageObj->save($newPath);
31
  }
32
- $resizedURL = Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_MEDIA) . "catalog" . DS . "product" . DS . "cache" . DS . "resized" . DS . $width . $fileName;
33
- } else {
34
- $resizedURL = $imageURL;
35
  }
36
- return $resizedURL; // $resizedURL;
 
 
 
 
 
 
 
 
 
 
 
 
 
37
  }
38
 
39
- public function getProductThumbnail($product, $width = NULL) {
 
40
  $gallery_data = $product->getData('media_gallery');
 
41
  if (!$gallery_data) {
42
  $attributes = $product->getTypeInstance(true)->getSetAttributes($product);
43
  $media_gallery = $attributes['media_gallery'];
@@ -51,17 +56,20 @@ class LetsSyncroLLC_Oct8ne_Helper_Image_Schuler extends LetsSyncroLLC_Oct8ne_Hel
51
  $gallery_info = $gallery_data['configurable_images'];
52
  }
53
  }
54
- $file = NULL;
55
- foreach ($gallery_info as $image) {
56
- $file = $image['file'];
57
- break;
58
- }
59
 
60
- if (!is_null($width)) {
61
- $fileName = $this->resizeImg($file, $width);
 
 
 
 
 
 
 
 
 
62
  }
63
-
64
- return $fileName;
65
  }
66
 
67
  }
2
 
3
  class LetsSyncroLLC_Oct8ne_Helper_Image_Schuler extends LetsSyncroLLC_Oct8ne_Helper_Image_Default {
4
 
5
+ public function getProductThumbnail($product, $width = null) {
 
 
 
 
 
6
 
7
+ $result = $this->getSchulerThumbnail($product);
8
+ return $result;
9
+ }
10
 
11
+ public function getProductImagesUrl($product) {
12
+ if (!$product->isConfigurable()) {
13
+ return parent::getProductImagesUrl($product);
14
+ }
15
+ // Process configurable products
16
+ $childProducts = Mage::getModel('catalog/product_type_configurable')->getUsedProducts(null, $product);
17
+ $images = array();
18
+ foreach ($childProducts as $simpleProduct) {
19
+ if ($simpleProduct->isSaleable()) {
20
+ $simpleProductImages = parent::getProductImagesUrl($simpleProduct);
21
+ foreach($simpleProductImages as $productImage) {
22
+ $images[] = $productImage["url"];
23
  }
 
 
 
 
 
 
24
  }
 
 
 
25
  }
26
+
27
+ // If no simple product images available, just return configurable product's images
28
+ if (count($images) == 0) {
29
+ return parent::getProductImagesUrl($product);
30
+ }
31
+
32
+ $images = array_unique($images); // Remove duplicates
33
+ $result = array();
34
+ foreach ($images as $img) {
35
+ $result[] = array(
36
+ 'url' => $img
37
+ );
38
+ }
39
+ return $result;
40
  }
41
 
42
+ public function getSchulerThumbnail($product) {
43
+ $profiler = $this->getProfiler(); /* @var $profiler LetsSyncroLLC_Oct8ne_Helper_Debug */
44
  $gallery_data = $product->getData('media_gallery');
45
+ $start = $profiler->startProfile();
46
  if (!$gallery_data) {
47
  $attributes = $product->getTypeInstance(true)->getSetAttributes($product);
48
  $media_gallery = $attributes['media_gallery'];
56
  $gallery_info = $gallery_data['configurable_images'];
57
  }
58
  }
 
 
 
 
 
59
 
60
+ $mustIgnoreExcludedImages = Mage::getStoreConfig('oct8neData/productData/ignoreExcludedImages');
61
+ foreach ($gallery_info as $image) {
62
+ $fileName = $image['file'];
63
+ $isImageExcluded = $image['disabled'] == '1' || $image['disabled_default'] == '1';
64
+ if (!$isImageExcluded || !$mustIgnoreExcludedImages) {
65
+ $physicalPath = Mage::getBaseDir(Mage_Core_Model_Store::URL_TYPE_MEDIA) . DS . $this->getProductDir($fileName);
66
+ if (is_file($physicalPath)) {
67
+ $file = Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_MEDIA) . $this->getProductDir($fileName);
68
+ return $file;
69
+ }
70
+ }
71
  }
72
+ return $this->getPlaceholder(200, 200);
 
73
  }
74
 
75
  }
app/code/community/LetsSyncroLLC/Oct8ne/Helper/Search/Base.php CHANGED
@@ -17,20 +17,31 @@ abstract class LetsSyncroLLC_Oct8ne_Helper_Search_Base extends Mage_Core_Helper_
17
  // $configurationString example:
18
  // key1=value1;key2=value2
19
  $configurationString = Mage::getStoreConfig('oct8neSearch/searchEngine/params');
20
-
 
 
 
 
 
21
  if (!is_null($configurationString) && strlen($configurationString) > 0) {
22
  $lines = explode(';', $configurationString);
23
  foreach ($lines as $line) {
24
  $keyValue = explode('=', $line);
25
  if (count($keyValue) == 2) {
26
- $this->params[trim($keyValue[0])] = trim($keyValue[1]);
 
 
 
27
  }
28
  }
29
  }
30
  }
31
 
32
  protected function getEngineParam($param) {
33
- return $this->params[$param];
 
 
 
34
  }
35
 
36
  public function getRequest() {
@@ -75,6 +86,66 @@ abstract class LetsSyncroLLC_Oct8ne_Helper_Search_Base extends Mage_Core_Helper_
75
  return $result;
76
  }
77
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
78
  protected function log($message) {
79
  $debug = Mage::helper('oct8ne/debug'); /* @var $debug LetsSyncroLLC_Oct8ne_Helper_Debug */
80
  $engineName = $this->getEngineName();
17
  // $configurationString example:
18
  // key1=value1;key2=value2
19
  $configurationString = Mage::getStoreConfig('oct8neSearch/searchEngine/params');
20
+ $currentLocaleCode = strtolower(Mage::app()->getLocale()->getLocaleCode());
21
+ if(strlen($currentLocaleCode) > 2) {
22
+ $currentLocaleCode = substr($currentLocaleCode, 0, 2);
23
+ }
24
+ $currentStoreId = Mage::app()->getStore()->getStoreId();
25
+
26
  if (!is_null($configurationString) && strlen($configurationString) > 0) {
27
  $lines = explode(';', $configurationString);
28
  foreach ($lines as $line) {
29
  $keyValue = explode('=', $line);
30
  if (count($keyValue) == 2) {
31
+ $key = trim($keyValue[0]);
32
+ $value = str_replace('$lang', $currentLocaleCode, $keyValue[1]);
33
+ $value = str_replace('$storeId', $currentStoreId, $keyValue[1]);
34
+ $this->params[$key] = trim($value);
35
  }
36
  }
37
  }
38
  }
39
 
40
  protected function getEngineParam($param) {
41
+ if (isset($this->params[$param])) {
42
+ return trim($this->params[$param]);
43
+ }
44
+ return NULL;
45
  }
46
 
47
  public function getRequest() {
86
  return $result;
87
  }
88
 
89
+ /**
90
+ * Creates am AppliedFilter structure
91
+ * @param string $param Parameter name
92
+ * @param string $param Parameter display name
93
+ * @param number $value Parameter value
94
+ * @param number $valueLabel Parameter value display text
95
+ * @return An AppliedFilter object
96
+ */
97
+ protected function createAppliedFilter($param, $paramLabel, $value, $valueLabel) {
98
+
99
+ return array(
100
+ "param" => $param,
101
+ "paramLabel" => $paramLabel,
102
+ "value" => $value,
103
+ "valueLabel" => $valueLabel
104
+ );
105
+ }
106
+
107
+ /*
108
+ * Gets the filters from the query string parameters
109
+ * @return Dictionary of filter query string parameters
110
+ */
111
+ protected function getAppliedFilters() {
112
+ $request = $this->getRequest();
113
+ $queryStringParams = array_keys($_GET);
114
+ $facets = array();
115
+ foreach ($queryStringParams as $param) {
116
+ // Ignore standard query standard params
117
+ if (substr($param, 0, 1) == '_' || $param == 'callback' || $param == 'search' || $param == 'store' || $param == 'orderby' || $param == 'dir' || $param == 'page' || $param == 'pageSize') {
118
+ continue;
119
+ }
120
+
121
+ // If we get here, the param is a facet
122
+ $value = $request->getParam($param);
123
+ if (!is_null($value) && trim($value)!="") {
124
+ $facets[$param] = $value;
125
+ }
126
+ }
127
+ return $facets;
128
+ }
129
+
130
+ /* Return the available filters that have not been applied
131
+ * @param $attrs_applied Array of applied filters
132
+ * @param $attrs_available Array of all available filters
133
+ * @return Available filters without appliend filters
134
+ */
135
+ protected function getAvailableButNotAppliedFilters($attrs_applied, $attrs_available) {
136
+ $result = array();
137
+ $applied = array();
138
+ foreach ($attrs_applied as $attr) {
139
+ $applied[$attr["param"]] = 1;
140
+ }
141
+ foreach ($attrs_available as $attr) {
142
+ if (!isset($applied[$attr["param"]])) {
143
+ $result[] = $attr;
144
+ }
145
+ }
146
+ return $result;
147
+ }
148
+
149
  protected function log($message) {
150
  $debug = Mage::helper('oct8ne/debug'); /* @var $debug LetsSyncroLLC_Oct8ne_Helper_Debug */
151
  $engineName = $this->getEngineName();
app/code/community/LetsSyncroLLC/Oct8ne/Helper/Search/Celebros.php ADDED
@@ -0,0 +1,241 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /* Celebros Search engine adapter
4
+ * Parameters
5
+ * - host: Celebros host (not including protocol)
6
+ * - port: port
7
+ * - siteKey: Site key
8
+ * - id_field: Field containing the product id
9
+ * - name_field: Field containing the product name. Used for sorting.
10
+ * - price_field: Field containing the price. Used for sorting.
11
+ *
12
+ * Example:
13
+ * host=http://xxx.xxx.xxx;port=6035;siteKey=abcde;id_field=mag_id;name_field=Title
14
+ *
15
+ */
16
+ /*
17
+ host=ezupv8-search.celebros.com;
18
+ port=6035;
19
+ siteKey=EZupV8;
20
+ id_field=mag_id;
21
+ name_field=Title;
22
+ price_field=Price;
23
+ */
24
+
25
+ include_once("CelebrosAPI/QwiserSearchAPI.php");
26
+
27
+ class LetsSyncroLLC_Oct8ne_Helper_Search_Celebros extends LetsSyncroLLC_Oct8ne_Helper_Search_Base {
28
+
29
+ public function getEngineName() {
30
+ return "celebros";
31
+ }
32
+
33
+ public function isValidSearchCriteria($searchTerm) {
34
+ if (is_null($searchTerm) || strlen($searchTerm) == 0) {
35
+ return false;
36
+ }
37
+ return true;
38
+ }
39
+
40
+ public function search($storeId, $searchTerm, $searchOrder, $searchDir, $page, $pageSize, &$totalSearchResults, &$attrs_applied, &$attrs_available) {
41
+ $handlerCookieName = "shandler";
42
+ $this->log("Searching " . $searchTerm);
43
+
44
+ $appliedFiltersDictionary = $this->getAppliedFilters();
45
+
46
+ if (($page > 1) && isset($_COOKIE[$handlerCookieName])) { // Change the page of the last query
47
+ $searchHandle = $_COOKIE[$handlerCookieName];
48
+ $result = $this->moveToPage($searchHandle, $page - 1);
49
+ } else if (($appliedFiltersDictionary) && isset($_COOKIE[$handlerCookieName])) { // We must apply filters on the last
50
+ $searchHandle = $_COOKIE[$handlerCookieName];
51
+ $result = $this->applyFilters($searchHandle, $appliedFiltersDictionary);
52
+ } else {
53
+ $result = $this->executeFullCelebrosSearchQuery($searchTerm, NULL, $searchOrder, $searchDir, $page, $pageSize, TRUE /* addFacets */);
54
+ }
55
+
56
+ // Return if no results found
57
+ if (!$result) {
58
+ return array();
59
+ }
60
+
61
+ // If we are browing the first page, we must store the search handle
62
+ // in a session cookie for reusing it in the next requests.
63
+ if ($page == 1 && !$appliedFiltersDictionary) {
64
+ $searchHandle = $result->QwiserSearchResults->myDOMNode->getAttribute("SearchHandle");
65
+ setcookie($handlerCookieName, $searchHandle, 0);
66
+ }
67
+
68
+ $totalSearchResults = $result->QwiserSearchResults->myDOMNode->getAttribute("RelevantProductsCount");
69
+ $currentPage = $result->SearchInformation->CurrentPage;
70
+ $productIds = $this->getProductIds($result);
71
+ $allAvailableFilters = $this->getAvailableFilters($result);
72
+ $attrs_applied = $this->getResponseAppliedFilters($allAvailableFilters, $appliedFiltersDictionary);
73
+ $attrs_available = $this->getAvailableButNotAppliedFilters($attrs_applied, $allAvailableFilters);
74
+
75
+ $this->log("Total {$totalSearchResults}, ids of this page: [" . implode(",", $productIds) . "]");
76
+ return $productIds;
77
+ }
78
+
79
+ public function getRelatedProductIds($product, $page, $pageSize) {
80
+
81
+ // Improvement: we can get the answers for this product (function GetProductAnswers()),
82
+ // and then try performing searches using this answers as criteria until we get results
83
+
84
+ $name = $product->getName();
85
+ $term = "";
86
+ foreach (explode(" ", $name) as $word) {
87
+ $trimmed = trim($word);
88
+ if ($trimmed != "" && strlen($trimmed) >= 2) {
89
+ if ($term != "") {
90
+ $term .= " OR ";
91
+ }
92
+ $term .= $word;
93
+ }
94
+ }
95
+ $result = $this->executeFullCelebrosSearchQuery($term, NULL, 'score', 'asc', $page, $pageSize, FALSE /* addFacets */);
96
+ if(!$result) {
97
+ return array();
98
+ }
99
+ $productIds = $this->getProductIds($result);
100
+ return $productIds;
101
+ }
102
+
103
+ private function moveToPage($searchHandle, $page) {
104
+ $api = $this->createApi();
105
+ $result = $api->moveToPage($searchHandle, $page);
106
+ if (!$result) {
107
+ $this->log("Move to page without results. Last operation message: $api->LastOperationErrorMessage");
108
+ }
109
+ return $result;
110
+ }
111
+
112
+ private function applyFilters($searchHandle, $appliedFilters) {
113
+ $api = $this->createApi();
114
+
115
+ $filters = "";
116
+ $separator = urlencode("#");
117
+ foreach ($appliedFilters as $param => $value) {
118
+ if ($filters != "") {
119
+ $filters .= $separator;
120
+ }
121
+ $filters .= $value;
122
+ }
123
+ $result = $api->AnswerQuestions($searchHandle, $filters, "1");
124
+ if (!$result) {
125
+ $this->log("Apply filters without results. Last operation message: $api->LastOperationErrorMessage");
126
+ }
127
+ return $result;
128
+ }
129
+
130
+ private function executeFullCelebrosSearchQuery($searchTerm = "", $searchCategories, $searchOrder, $searchDir, $page, $pageSize, $addFacets) {
131
+
132
+ $api = $this->createApi();
133
+ $searchProfile = "";
134
+ $answerId = "";
135
+ $effectOnSearchPath = "1"; // * 0-2, PDF pag 17
136
+ $priceColumn = ""; // Optional?
137
+ $sortingField = $this->getCelebrosSort($searchOrder);
138
+ $bNumericSort = $searchOrder=="price"? "1": "0";
139
+ $bAscending = $searchDir == "asc"? "1": "0";
140
+
141
+ if ($addFacets) {
142
+ $applied = $this->getAppliedFilters();
143
+ foreach ($applied as $param => $value) {
144
+ $answerId = $value;
145
+ break;
146
+ }
147
+ }
148
+
149
+ $result = $api->SearchAdvance($searchTerm, $searchProfile, $answerId, $effectOnSearchPath, $priceColumn, $pageSize, $sortingField, $bNumericSort, $bAscending);
150
+ if (!$result) {
151
+ $this->log("No results. Last operation message: $api->LastOperationErrorMessage");
152
+ }
153
+ return $result;
154
+ }
155
+
156
+ private function createApi() {
157
+ $port = $this->getEngineParam("port");
158
+ $host = $this->getEngineParam("host");
159
+ $siteKey = $this->getEngineParam("siteKey");
160
+ $api = new QwiserSearchAPI($siteKey, $host, $port);
161
+ return $api;
162
+ }
163
+
164
+ private function getProductIds($result) {
165
+ $productIds = array();
166
+ $idField = $this->getEngineParam('id_field');
167
+
168
+ if (!$result || !$result->Products)
169
+ return $productIds;
170
+
171
+ $products = $result->Products->Items;
172
+ foreach ($products as $product) {
173
+ $productIds[] = $product->Field[$idField];
174
+ }
175
+
176
+ // Uncomment for local testing
177
+ // $productIds = array('906', '875', '874', '554', '553', '552', '551', '549', '399', '398');
178
+
179
+ return $productIds;
180
+ }
181
+
182
+ private function getCelebrosSort($searchOrder) {
183
+ $result = "";
184
+ if (!$searchOrder) {
185
+ $searchOrder = "relevance";
186
+ }
187
+ switch ($searchOrder) {
188
+ case "score":
189
+ case "relevance":
190
+ $result = ""; // By default, the order is "relevance"
191
+ break;
192
+ case "price":
193
+ $result = $this->getEngineParam("price_field");
194
+ break;
195
+ case "name":
196
+ $result = $this->getEngineParam("name_field");
197
+ }
198
+ return $result;
199
+ }
200
+
201
+ private function getAvailableFilters($result) {
202
+ $filters = array();
203
+ $questions = $result->Questions;
204
+ foreach ($questions->Items as $question) {
205
+ $questionName = $question->Text;
206
+ $questionId = "a-" . $question->Id;
207
+ $answers = $question->Answers;
208
+ $options = array();
209
+ foreach ($answers->Items as $answer) {
210
+ $answerId = $answer->Id;
211
+ $answerName = $answer->Text;
212
+ $answerCount = $answer->ProductCount;
213
+ $options[] = $this->createFilterOption($answerName, $answerId, $answerCount);
214
+ }
215
+ $filters[] = $this->createFilterInfo($questionId, $questionName, $options);
216
+ }
217
+ return $filters;
218
+ }
219
+
220
+ private function getResponseAppliedFilters($availableFilters) {
221
+ $filters = array();
222
+ $request = $this->getRequest();
223
+
224
+ foreach ($availableFilters as $availableFilter) {
225
+ $parameterName = $availableFilter["param"];
226
+ $parameterLabel = $availableFilter["paramLabel"];
227
+ $parameterValue = $request->getParam($parameterName);
228
+ if (!is_null($parameterValue)) {
229
+ foreach ($availableFilter["options"] as $option) {
230
+ if ($option["value"] == $parameterValue) {
231
+ $filters[] = $this->createAppliedFilter(
232
+ $parameterName, $parameterLabel, $parameterValue, $option["valueLabel"]
233
+ );
234
+ break;
235
+ }
236
+ }
237
+ }
238
+ }
239
+ return $filters;
240
+ }
241
+ }
app/code/community/LetsSyncroLLC/Oct8ne/Helper/Search/CelebrosAPI/QwiserAnswer.php ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ Class QwiserAnswer
3
+ {
4
+ var $Id;
5
+ var $ImageHeight;
6
+ var $ImageSku;
7
+ var $ImageUrl;
8
+ var $ImageWidth;
9
+ var $ProductCount;
10
+ var $Text;
11
+ var $Type;
12
+ var $DynamicProperties;
13
+
14
+ Function QwiserAnswer($AnswerNode)
15
+ {
16
+ if(is_object($AnswerNode))
17
+ {
18
+ $this->Id = $AnswerNode->get_attribute("Id");
19
+ $this->ImageHeight = $AnswerNode->get_attribute("ImageHeight");
20
+ $this->ImageSku = $AnswerNode->get_attribute("ImageSku");
21
+ $this->ImageUrl = $AnswerNode->get_attribute("ImageUrl");
22
+ $this->ImageWidth = $AnswerNode->get_attribute("ImageWidth");
23
+ $this->ProductCount = $AnswerNode->get_attribute("ProductCount");
24
+ $this->Text = $AnswerNode->get_attribute("Text");
25
+ $this->Type = $AnswerNode->get_attribute("Type");
26
+ $this->DynamicProperties = GetQwiserSimpleStringDictionary(current($AnswerNode->get_elements_by_tagname("DynamicProperties")));
27
+ }
28
+ }
29
+ }
30
+ ?>
app/code/community/LetsSyncroLLC/Oct8ne/Helper/Search/CelebrosAPI/QwiserAnswers.php ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ Class QwiserAnswers
3
+ {
4
+ var $Count = 0; //the number of products
5
+ var $Items; //indexer .
6
+
7
+ Function QwiserAnswers($xml_Answers)
8
+ {
9
+ //if we got an array of QwiserAnswer
10
+ if(is_array($xml_Answers))
11
+ {
12
+ $this->Items = $xml_Answers;
13
+ $this->Count = count($xml_Answers);
14
+ }
15
+ //if we got a node of QwiserAnswers
16
+ else
17
+ {
18
+ if(is_object($xml_Answers))
19
+ {
20
+ $xml_AnswersNodes = $xml_Answers->child_nodes();
21
+ $xml_AnswersNodes = getDomElements($xml_AnswersNodes);
22
+ $this->Count = count($xml_AnswersNodes);
23
+
24
+ for ($i = 0 ; $i <= $this->Count - 1;$i++)
25
+ {
26
+ $AnswerNode = $xml_AnswersNodes[$i];
27
+ $this->Items[$i] = new QwiserAnswer($AnswerNode);
28
+ }
29
+ }
30
+ }
31
+ }
32
+
33
+ //Return Answer By Id.
34
+ Function GetAnswerById($ID)
35
+ {
36
+ foreach ($this->Items as $Ans)
37
+ {
38
+ if($Ans->Id=$ID)
39
+ {
40
+ return $ans;
41
+ }
42
+ }
43
+ }
44
+
45
+ //Gets a QwiserAnswers object of all answers in this collection that have the specified text
46
+ Function GetAnswersByText($Text)
47
+ {
48
+ $ansArray = array();
49
+ foreach ($this->Items as $Ans)
50
+ {
51
+ if($Ans->Text = $Text)
52
+ {
53
+ $ansArray[] = $Ans;
54
+ }
55
+ }
56
+ return new QwiserAnswers($ansArray);
57
+ }
58
+
59
+ //Gets a QwiserAnswers object of all answers in this collection that are of the specified type
60
+ Function GetAnswersByType($Type)
61
+ {
62
+ $ansArray = array();
63
+ foreach ($this->Items as $Ans)
64
+ {
65
+ if($Ans->Type = $Type)
66
+ {
67
+ $ansArray[] = $Ans;
68
+ }
69
+ }
70
+ return new QwiserAnswers($ansArray);
71
+ }
72
+
73
+ //Sorts This QwiserAnswers collection with CompareTo method.
74
+ Function SortByAnswerText()
75
+ {
76
+ usort($this->Items,array("QwiserAnswers","CompareTo"));
77
+ }
78
+
79
+ Function CompareTo($a,$b)
80
+ {
81
+ $al = strtolower($a->Text);
82
+ $bl = strtolower($b->Text);
83
+ if ($al == $bl) {
84
+ return 0;
85
+ }
86
+ return ($al > $bl) ? +1 : -1;
87
+ //return strcmp($a1,$b1);
88
+ }
89
+
90
+
91
+ }
92
+ ?>
app/code/community/LetsSyncroLLC/Oct8ne/Helper/Search/CelebrosAPI/QwiserConcept.php ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class QwiserConcept
3
+ {
4
+ var $Id; //the concept id.
5
+ var $Name; //the concept name.
6
+ var $Rank; //the concept rank.
7
+ var $Type; //the concept type(attribute,commodity,temathic).
8
+ var $DynamicProperties; //the concept dynamic properties.
9
+
10
+ function QwiserConcept($ConceptNode)
11
+ {
12
+ if(is_object($ConceptNode))
13
+ {
14
+ $this->Id = $ConceptNode->get_attribute("Id");
15
+ $this->Name = $ConceptNode->get_attribute("Name");
16
+ $this->Rank = $ConceptNode->get_attribute("Rank");
17
+ $this->Type = $ConceptNode->get_attribute("Type");
18
+ $this->DynamicProperties = GetQwiserSimpleStringDictionary(current($ConceptNode->get_elements_by_tagname("DynamicProperties")));
19
+ }
20
+ }
21
+ }
22
+ ?>
app/code/community/LetsSyncroLLC/Oct8ne/Helper/Search/CelebrosAPI/QwiserConcepts.php ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class QwiserConcepts
3
+ {
4
+ var $Count = 0; //number of concepts.
5
+ var $Items; //QwiserConcept array
6
+
7
+ function QwiserConcepts($xml_Concepts)
8
+ {
9
+ if(is_object($xml_Concepts))
10
+ {
11
+ $xml_ConceptsNodes = $xml_Concepts->child_nodes();
12
+ $xml_ConceptsNodes = getDomElements($xml_ConceptsNodes);
13
+ $this->Count = count($xml_ConceptsNodes);
14
+
15
+ for ($i = 0 ; $i <= $this->Count - 1;$i++)
16
+ {
17
+ $ConceptNode = $xml_ConceptsNodes[$i];
18
+ $this->Items[$i] = new QwiserConcept($ConceptNode);
19
+ }
20
+ }
21
+ }
22
+ }
23
+
24
+ ?>
app/code/community/LetsSyncroLLC/Oct8ne/Helper/Search/CelebrosAPI/QwiserProduct.php ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class QwiserProduct
3
+ {
4
+ var $Field;
5
+ var $FoundInAnswerId;
6
+ var $FoundInAnswerPath;
7
+ var $IsBestSeller;
8
+ var $MatchClassFound;
9
+ var $Price;
10
+ var $Sku;
11
+
12
+ function QwiserProduct($ProdNode)
13
+ {
14
+ if(is_object($ProdNode))
15
+ {
16
+ $this->Field = $this->GetProductCommonInformation($ProdNode);
17
+ $this->FoundInAnswerId = $ProdNode->get_attribute("FoundInAnswerId");
18
+ $this->FoundInAnswerPath = $ProdNode->get_attribute("FoundInAnswerPath");
19
+ $this->IsBestSeller = $ProdNode->get_attribute("IsBestSeller");
20
+ $this->MatchClassFound = $ProdNode->get_attribute("MatchClassFound");
21
+ $this->Price = $ProdNode->get_attribute("Price");
22
+ $this->Sku = $ProdNode->get_attribute("Sku");
23
+ }
24
+ }
25
+
26
+ function GetProductCommonInformation($ProdNode)
27
+ {
28
+ $ProductFields=current(getDomElements($ProdNode->child_nodes()));
29
+ $ProductFieldsArray=getDomElements($ProductFields->child_nodes());
30
+ foreach ($ProductFieldsArray as $Pfield)
31
+ {
32
+ $ProdField[$Pfield->get_attribute("name")] = $Pfield->get_attribute("value");
33
+ }
34
+ return $ProdField;
35
+ }
36
+ }
37
+ ?>
app/code/community/LetsSyncroLLC/Oct8ne/Helper/Search/CelebrosAPI/QwiserProductAnswer.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class QwiserProductAnswer
3
+ {
4
+ var $Id;
5
+ var $Name;
6
+ var $QuestionId;
7
+ var $Sku;
8
+
9
+ Function QwiserProductAnswer($ProductAnswerNode)
10
+ {
11
+ if(is_object($ProductAnswerNode))
12
+ {
13
+ $this->Id = $ProductAnswerNode->get_attribute("Id");
14
+ $this->Name = $ProductAnswerNode->get_attribute("Name");
15
+ $this->QuestionId = $ProductAnswerNode->get_attribute("QuestionId");
16
+ $this->Sku = $ProductAnswerNode->get_attribute("Sku");
17
+ }
18
+ }
19
+ }
20
+
21
+ ?>
app/code/community/LetsSyncroLLC/Oct8ne/Helper/Search/CelebrosAPI/QwiserProductAnswers.php ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class QwiserProductAnswers
3
+ {
4
+ var $Count;
5
+ var $Items;
6
+ Function QwiserProductAnswers($xml_ProductAnswers)
7
+ {
8
+ if(is_object($xml_ProductAnswers))
9
+ {
10
+ $xml_ProductAnswersNodes = $xml_ProductAnswers->child_nodes();
11
+ $xml_ProductAnswersNodes = getDomElements($xml_ProductAnswersNodes);
12
+ $this->Count = count($xml_ProductAnswersNodes);
13
+
14
+ for ($i = 0 ; $i <= $this->Count - 1;$i++)
15
+ {
16
+ $ProductAnswerNode = $xml_ProductAnswersNodes[$i];
17
+ $this->Items[$i] = new QwiserProductAnswer($ProductAnswerNode);
18
+ }
19
+ }
20
+ }
21
+ }
22
+ ?>
app/code/community/LetsSyncroLLC/Oct8ne/Helper/Search/CelebrosAPI/QwiserProductField.php ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class QwiserProductField
3
+ {
4
+ var $FieldType;
5
+ var $Name;
6
+
7
+
8
+ Function QwiserProductField($ProductFieldNode)
9
+ {
10
+ if(is_object($ProductFieldNode))
11
+ {
12
+ $this->FieldType = $ProductFieldNode->get_attribute("FieldType");
13
+ $this->Name = $ProductFieldNode->get_attribute("Name");
14
+ }
15
+ }
16
+ }
17
+ ?>
app/code/community/LetsSyncroLLC/Oct8ne/Helper/Search/CelebrosAPI/QwiserProductFields.php ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class QwiserProductFields
3
+ {
4
+ var $Count;
5
+ var $Items;
6
+
7
+ Function QwiserProductFields($xml_ProductFields)
8
+ {
9
+ if(is_object($xml_ProductFields))
10
+ {
11
+ $xml_ProductFieldsNodes = $xml_ProductFields->child_nodes();
12
+ $xml_ProductFieldsNodes = getDomElements($xml_ProductFieldsNodes);
13
+ $this->Count = count($xml_ProductFieldsNodes);
14
+ for ($i = 0 ; $i <= $this->Count - 1;$i++)
15
+ {
16
+ $ProductFieldNode = $xml_ProductFieldsNodes[$i];
17
+ $this->Items[$i] = new QwiserProductField($ProductFieldNode);
18
+ }
19
+ }
20
+ }
21
+ }
22
+ ?>
app/code/community/LetsSyncroLLC/Oct8ne/Helper/Search/CelebrosAPI/QwiserProducts.php ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class QwiserProducts
3
+ {
4
+ var $Count = 0; //the number of products.
5
+ var $Items; //indexer .
6
+
7
+ Function QwiserProducts($xml_Products)
8
+ {
9
+ if(is_object($xml_Products))
10
+ {
11
+ $xml_productsNodes = $xml_Products->child_nodes();
12
+ $xml_productsNodes = getDomElements($xml_productsNodes);
13
+ $this->Count = count($xml_productsNodes);
14
+
15
+ for ($i = 0 ; $i <= $this->Count - 1;$i++)
16
+ {
17
+ $ProdNode = $xml_productsNodes[$i];
18
+ $this->Items[$i] = new QwiserProduct($ProdNode);
19
+ }
20
+ }
21
+ }
22
+
23
+
24
+ }
25
+ ?>
app/code/community/LetsSyncroLLC/Oct8ne/Helper/Search/CelebrosAPI/QwiserProductsMetaData.php ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class QwiserProductsMetaData
3
+ {
4
+ var $ProductCount;
5
+
6
+ function QwiserProductsMetaData($MetadataNode)
7
+ {
8
+ if(is_object($MetadataNode))
9
+ {
10
+ $this->ProductCount = $MetadataNode->get_attribute("Count");
11
+ }
12
+ }
13
+ }
14
+ ?>
app/code/community/LetsSyncroLLC/Oct8ne/Helper/Search/CelebrosAPI/QwiserQuestion.php ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class QwiserQuestion
3
+ {
4
+ var $Id;
5
+ var $Rank;
6
+ var $SideText;
7
+ var $Text;
8
+ var $Type;
9
+ var $HasMoreAnswers;
10
+ var $ExtraAnswers;
11
+ var $DynamicProperties;
12
+ var $Answers;
13
+
14
+ Function QwiserQuestion($QuestionNode)
15
+ {
16
+ if(is_object($QuestionNode))
17
+ {
18
+ $this->Id = $QuestionNode->get_attribute("Id");
19
+ $this->Rank = $QuestionNode->get_attribute("Rank");
20
+ $this->SideText = $QuestionNode->get_attribute("SideText");
21
+ $this->Text = $QuestionNode->get_attribute("Text");
22
+ $this->Type = $QuestionNode->get_attribute("Type");
23
+ $this->Answers = new QwiserAnswers(current($QuestionNode->get_elements_by_tagname("Answers")));
24
+ $this->ExtraAnswers = new QwiserAnswers(current($QuestionNode->get_elements_by_tagname("ExtraAnswers")));
25
+ $this->HasMoreAnswers = ($this->ExtraAnswers->Count > 0) ? true : false;
26
+ $this->DynamicProperties = GetQwiserSimpleStringDictionary(current($QuestionNode->get_elements_by_tagname("DynamicProperties")));
27
+ }
28
+ }
29
+ }
30
+ ?>
app/code/community/LetsSyncroLLC/Oct8ne/Helper/Search/CelebrosAPI/QwiserQuestions.php ADDED
@@ -0,0 +1,87 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class QwiserQuestions
3
+ {
4
+ var $Count; //the number of questions.
5
+ var $Items; //indexer .
6
+
7
+ Function QwiserQuestions($xml_Questions)
8
+ {
9
+ if(is_array($xml_Questions))
10
+ {
11
+ $this->Items = $xml_Questions;
12
+ $this->Count = count($xml_Questions);
13
+ }
14
+ else
15
+ {
16
+ if(is_object($xml_Questions))
17
+ {
18
+ $xml_questionsNodes = $xml_Questions->child_nodes();
19
+ $xml_questionsNodes = getDomElements($xml_questionsNodes);
20
+ $this->Count = count($xml_questionsNodes);
21
+
22
+ for ($i = 0 ; $i <= $this->Count - 1;$i++)
23
+ {
24
+ $QuestionNode = $xml_questionsNodes[$i];
25
+ $this->Items[$i] = new QwiserQuestion($QuestionNode);
26
+ }
27
+ }
28
+ }
29
+
30
+ }
31
+
32
+ //get a question by its id .
33
+ Function GetQuestionById($ID)
34
+ {
35
+ foreach ($this->Items as $q)
36
+ {
37
+ if($q->Id=$ID)
38
+ {
39
+ return $q;
40
+ }
41
+ }
42
+ }
43
+
44
+ //get all questions with the given side text
45
+ Function GetQuestionsBySideText($SideText)
46
+ {
47
+ $qArray = array();
48
+ foreach ($this->Items as $q)
49
+ {
50
+ if($q->SideText=$SideText)
51
+ {
52
+ $qArray[] = $q;
53
+ }
54
+ }
55
+ return $qArray;
56
+ }
57
+
58
+ //get all question with the given text .
59
+ Function GetQuestionsByText($QuestionText)
60
+ {
61
+ $qArray = array();
62
+ foreach ($this->Items as $q)
63
+ {
64
+ if($q->Text=$QuestionText)
65
+ {
66
+ $qArray[] = $q;
67
+ }
68
+ }
69
+ return $qArray;
70
+ }
71
+
72
+ //get all question with the given type .
73
+ Function GetQuestionsByType($Type)
74
+ {
75
+ $qArray = array();
76
+ foreach ($this->Items as $q)
77
+ {
78
+ if($q->Type=$Type)
79
+ {
80
+ $qArray[] = $q;
81
+ }
82
+ }
83
+ return $qArray;
84
+
85
+ }
86
+ }
87
+ ?>
app/code/community/LetsSyncroLLC/Oct8ne/Helper/Search/CelebrosAPI/QwiserSearchAPI.php ADDED
@@ -0,0 +1,428 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ include("SearchInformation.php");
3
+ include("QwiserSearchResults.php");
4
+ include("QwiserProducts.php");
5
+ include("QwiserProduct.php");
6
+ include("SortingOptions.php");
7
+ include("QwiserQuestions.php");
8
+ include("QwiserQuestion.php");
9
+ include("QwiserAnswers.php");
10
+ include("QwiserAnswer.php");
11
+ include("QwiserSearchPath.php");
12
+ include("QwiserSearchPathEntry.php");
13
+ include("QwiserSpellerInformation.php");
14
+ include("QwiserConcepts.php");
15
+ include("QwiserConcept.php");
16
+ include("QwiserProductAnswers.php");
17
+ include("QwiserProductAnswer.php");
18
+ include("QwiserProductFields.php");
19
+ include("QwiserProductField.php");
20
+ include("domxml-php4-to-php5.php");
21
+
22
+
23
+ class QwiserSearchAPI
24
+ {
25
+ var $CommunicationPort; //The name of the comm port to use for access to the search server.
26
+ var $HostName; //The name of the search server to connect to.
27
+ var $SiteKey; //the api site key.
28
+ var $LastOperationErrorMessage; //the last operation error message.
29
+ var $LastOperationSucceeded; //return true if the last operation ended successfully.
30
+ var $WebService; //Search WebService full uri.
31
+ var $Context ;
32
+
33
+ /**
34
+ * Constructor
35
+ **/
36
+ Function QwiserSearchAPI($SiteKey,$HostName,$CommunicationPort)
37
+ {
38
+ $this->HostName = $HostName;
39
+ $this->CommunicationPort = $CommunicationPort;
40
+ $this->SiteKey = $SiteKey;
41
+ $this->WebService ="http://".$this->HostName.":".$this->CommunicationPort."/";
42
+ $this->LastOperationSucceeded = true;
43
+
44
+ $opts = array(
45
+ 'http'=>array(
46
+ 'method'=>"GET",
47
+ 'header'=>"Accept-Language: en-US,en;q=0.8rn" .
48
+ "Accept-Encoding: gzip, deflate" .
49
+ "Accept-Charset: UTF-8,*;q=0.5rn" .
50
+ "User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:19.0) Gecko/20100101 Firefox/19.0 FirePHP/0.4rn"
51
+ )
52
+ );
53
+
54
+ $Context = stream_context_create($opts);
55
+
56
+ }
57
+
58
+
59
+ //Activate serach Profile
60
+ Function ActivateProfile($SearchHandle,$SearchProfile)
61
+ {
62
+ $SearchProfile = urlencode($SearchProfile);
63
+ $RequestUrl = "ActivateProfile?SearchHandle=".$SearchHandle."&SearchProfile=".$SearchProfile."&Sitekey=".$this->SiteKey;
64
+ return $this->GetResult($RequestUrl,"QwiserSearchResults");
65
+ }
66
+
67
+ //Answer Question
68
+ Function AnswerQuestion($SearchHandle,$AnswerId,$EffectOnSearchPath)
69
+ {
70
+ $RequestUrl = "AnswerQuestion?SearchHandle=".$SearchHandle."&answerId=".$AnswerId."&EffectOnSearchPath=".$EffectOnSearchPath."&Sitekey=".$this->SiteKey;
71
+ return $this->GetResult($RequestUrl,"QwiserSearchResults");
72
+ }
73
+
74
+ //Answer Question
75
+ Function AnswerQuestions($SearchHandle,$AnswerIds,$EffectOnSearchPath)
76
+ {
77
+ $RequestUrl = "AnswerQuestions?SearchHandle=".$SearchHandle."&answerIds=".$AnswerIds."&EffectOnSearchPath=".$EffectOnSearchPath."&Sitekey=".$this->SiteKey;
78
+ return $this->GetResult($RequestUrl,"QwiserSearchResults");
79
+ }
80
+
81
+ //Change Number of Products in Page
82
+ Function ChangePageSize($SearchHandle,$PageSize)
83
+ {
84
+ $RequestUrl = "ChangePageSize?SearchHandle=".$SearchHandle."&pageSize=".$PageSize."&Sitekey=".$this->SiteKey;
85
+ return $this->GetResult($RequestUrl,"QwiserSearchResults");
86
+ }
87
+
88
+ //Change the search default price
89
+ Function ChangePriceColumn($SearchHandle,$PriceColumn)
90
+ {
91
+ $RequestUrl = "ChangePriceColumn?SearchHandle=".$SearchHandle."&PriceColumn=".$PriceColumn."&Sitekey=".$this->SiteKey;
92
+ return $this->GetResult($RequestUrl,"QwiserSearchResults");
93
+ }
94
+
95
+ //Deactivate Search Profile
96
+ Function DeactivateProfile($SearchHandle)
97
+ {
98
+ $RequestUrl = "DeactivateProfile?SearchHandle=".$SearchHandle."&Sitekey=".$this->SiteKey;
99
+ return $this->GetResult($RequestUrl,"QwiserSearchResults");
100
+ }
101
+
102
+ //Moves to the first page of the results
103
+ Function FirstPage($SearchHandle)
104
+ {
105
+ $RequestUrl = "FirstPage?SearchHandle=".$SearchHandle."&Sitekey=".$this->SiteKey;
106
+ return $this->GetResult($RequestUrl,"QwiserSearchResults");
107
+ }
108
+
109
+ //Forces the BQF to allow the specified question to appear first
110
+ Function ForceQuestionAsFirst($SearchHandle,$QuestionId)
111
+ {
112
+ $RequestUrl = "ForceQuestionAsFirst?SearchHandle=".$SearchHandle."&QuestionId=".$QuestionId."&Sitekey=".$this->SiteKey;
113
+ return $this->GetResult($RequestUrl,"QwiserSearchResults");
114
+ }
115
+
116
+ //Gets the results for the specified search handle
117
+ Function GetCustomResults($SearchHandle,$bNewSearch,$PreviousSearchHandle)
118
+ {
119
+ $RequestUrl = "GetCustomResults?SearchHandle=".$SearchHandle."&NewSearch=".$bNewSearch."&PreviousSearchHandle=".$PreviousSearchHandle."&Sitekey=".$this->SiteKey;
120
+ return $this->GetResult($RequestUrl,"QwiserSearchResults");
121
+ }
122
+
123
+ //Return the LastPage.
124
+ Function LastPage($SearchHandle)
125
+ {
126
+ $RequestUrl = "LastPage?SearchHandle=".$SearchHandle."&Sitekey=".$this->SiteKey;
127
+ return $this->GetResult($RequestUrl,"QwiserSearchResults");
128
+ }
129
+
130
+ //Moves to the specified page of the results
131
+ Function MoveToPage($SearchHandle,$Page)
132
+ {
133
+ $RequestUrl = "MoveToPage?SearchHandle=".$SearchHandle."&Page=".$Page."&Sitekey=".$this->SiteKey;
134
+ return $this->GetResult($RequestUrl,"QwiserSearchResults");
135
+ }
136
+
137
+ //Moves to the previous page of the results
138
+ Function PreviousPage($SearchHandle)
139
+ {
140
+ $RequestUrl = "PreviousPage?SearchHandle=".$SearchHandle."&Sitekey=".$this->SiteKey;
141
+ return $this->GetResult($RequestUrl,"QwiserSearchResults");
142
+ }
143
+
144
+ //Moves to the next page of the results
145
+ Function NextPage($SearchHandle)
146
+ {
147
+ $RequestUrl = "NextPage?SearchHandle=".$SearchHandle."&Sitekey=".$this->SiteKey;
148
+ return $this->GetResult($RequestUrl,"QwiserSearchResults");
149
+ }
150
+
151
+ //Removes the specified answer from the list of answered answers in this session.
152
+ Function RemoveAnswer($SearchHandle,$AnswerId)
153
+ {
154
+ $RequestUrl = "RemoveAnswer?SearchHandle=".$SearchHandle."&AnswerId=".$AnswerId."&Sitekey=".$this->SiteKey;
155
+ return $this->GetResult($RequestUrl,"QwiserSearchResults");
156
+ }
157
+
158
+ //Removes the specified answers from the list of answered answers in this session.
159
+ Function RemoveAnswerAt($SearchHandle,$AnswerIndex)
160
+ {
161
+ $RequestUrl = "RemoveAnswerAt?SearchHandle=".$SearchHandle."&AnswerIndex=".$AnswerIndex."&Sitekey=".$this->SiteKey;
162
+ return $this->GetResult($RequestUrl,"QwiserSearchResults");
163
+ }
164
+
165
+ //Removes the specified answers from the list of answered answers in this session.
166
+ Function RemoveAnswers($SearchHandle,$AnswerIds)
167
+ {
168
+ $RequestUrl = "RemoveAnswers?SearchHandle=".$SearchHandle."&AnswerIds=".$AnswerIds."&Sitekey=".$this->SiteKey;
169
+ return $this->GetResult($RequestUrl,"QwiserSearchResults");
170
+ }
171
+
172
+ //Remove the all the answer from the search information form the given index
173
+ Function RemoveAnswersFrom($SearchHandle,$StartIndex)
174
+ {
175
+ $RequestUrl = "RemoveAnswersFrom?SearchHandle=".$SearchHandle."&StartIndex=".$StartIndex."&Sitekey=".$this->SiteKey;
176
+ return $this->GetResult($RequestUrl,"QwiserSearchResults");
177
+ }
178
+
179
+
180
+ //Gets the results for the specified search term.
181
+ Function Search($Query)
182
+ {
183
+ $Query = urlencode($Query);
184
+ $RequestUrl = "search?Query=".$Query."&sitekey=".$this->SiteKey;
185
+ return $this->GetResult($RequestUrl,"QwiserSearchResults");
186
+ }
187
+
188
+ //Gets the results for the specified search term under the specified search profile and the answer which Id was specified.
189
+ Function SearchAdvance($Query,$SearchProfile,$AnswerId,$EffectOnSearchPath,$PriceColumn,$PageSize,$Sortingfield,$bNumericsort,$bAscending)
190
+ {
191
+ $Query = urlencode($Query);
192
+ $SearchProfile = urlencode($SearchProfile);
193
+ $Sortingfield = urlencode($Sortingfield);
194
+ $PriceColumn = urlencode($PriceColumn);
195
+ $RequestUrl = "SearchAdvance?Query=".$Query."&SearchProfile=".$SearchProfile."&AnswerId=".$AnswerId."&EffectOnSearchPath=".$EffectOnSearchPath."&PriceColumn=".$PriceColumn."&PageSize=".$PageSize."&Sortingfield=".$Sortingfield."&Numericsort=".$bNumericsort."&Ascending=".$bAscending."&sitekey=".$this->SiteKey;
196
+ return $this->GetResult($RequestUrl,"QwiserSearchResults");
197
+ }
198
+
199
+ //set the general params of the api
200
+ Function SetQwiserSearchAPI($siteKey ,$serverName ,$port )
201
+ {
202
+ $this->SiteKey = $siteKey;
203
+ $this->HostName = $serverName;
204
+ $this->CommunicationPort = $port;
205
+ }
206
+
207
+ //Changes the sorting of the results to display products by the value of the specified field, and whether to perform a numeric sort on that field, in the specified sorting direction.
208
+ Function SortByField($SearchHandle,$FieldName,$bNumericSort,$bAscending)
209
+ {
210
+ $FieldName = urlencode($FieldName);
211
+ $RequestUrl = "SortByField?SearchHandle=".$SearchHandle."&FieldName=".$FieldName."&NumericSort=".$bNumericSort."&Ascending=".$bAscending."&sitekey=".$this->SiteKey;
212
+ return $this->GetResult($RequestUrl,"QwiserSearchResults");
213
+ }
214
+
215
+ //Changes the sorting of the results to display products by their price in the specified sorting direction
216
+ Function SortByPrice($SearchHandle,$bAscending)
217
+ {
218
+ $RequestUrl = "SortByPrice?SearchHandle=".$SearchHandle."&Ascending=".$bAscending."&sitekey=".$this->SiteKey;
219
+ return $this->GetResult($RequestUrl,"QwiserSearchResults");
220
+ }
221
+
222
+ //Changes the sorting of the results to display products by relevancy in descending order.
223
+ Function SortByRelevancy($SearchHandle)
224
+ {
225
+ $RequestUrl = "SortByRelevancy?SearchHandle=".$SearchHandle."&Sitekey=".$this->SiteKey;
226
+ return $this->GetResult($RequestUrl,"QwiserSearchResults");
227
+ }
228
+
229
+ //Marks a product as out of stock.
230
+ Function RemoveProductFromStock($Sku)
231
+ {
232
+ $Sku = urlencode($Sku);
233
+ $RequestUrl = "RemoveProductFromStock?Sku=".$Sku."&Sitekey=".$this->SiteKey;
234
+ return $this->GetResult($RequestUrl,"String");
235
+ }
236
+
237
+ //Marks a product as in stock.
238
+ Function RestoreProductToStock($Sku)
239
+ {
240
+ $Sku = urlencode($Sku);
241
+ $RequestUrl = "RestoreProductToStock?Sku=".$Sku."&Sitekey=".$this->SiteKey;
242
+ return $this->GetResult($RequestUrl,"String");
243
+ }
244
+
245
+ Function UpdateProductPrice($Sku, $Price, $FieldName, $SearchProfile)
246
+ {
247
+ $RequestUrl = "UpdateProductPrice?Sitekey=".$this->SiteKey."&Sku=".$Sku."&Price=".$Price."&Fieldname=".$FieldName."&Profilename=".$SearchProfile;
248
+ $this->GetResult($RequestUrl, "");
249
+ }
250
+
251
+ Function GetProductsMetaData()
252
+ {
253
+ $RequestUrl = "GetProductsMetaData?Sitekey=".$this->SiteKey ;
254
+ return $this->GetResult($RequestUrl,"QwiserProductsMetaData");
255
+ }
256
+
257
+ Function getUrl($url)
258
+ {
259
+ $content = file_get_contents($url , false, $this->Context);
260
+
261
+ if($content == FALSE)
262
+ {
263
+ return FALSE ;
264
+ }
265
+
266
+ //If http response header mentions that content is gzipped, then uncompress it
267
+ foreach($http_response_header as $c => $h)
268
+ {
269
+ if(stristr($h, 'content-encoding') and stristr($h, 'gzip'))
270
+ {
271
+ //Now lets uncompress the compressed data
272
+ $content = gzinflate( substr($content,10,-8) );
273
+ }
274
+ }
275
+
276
+ return $content;
277
+ }
278
+
279
+ //Gets the xml file, parse it and chack for Errors.
280
+ Function GetResult($RequestUrl,$ReturnValue)
281
+ {
282
+ $xml_file = $this->getUrl($this->WebService.$RequestUrl) ;
283
+
284
+ //file_get_contents return value should be true.
285
+ if($xml_file === FALSE)
286
+ {
287
+ $this->LastOperationSucceeded = false;
288
+ $this->LastOperationErrorMessage = "Error : could not GET XML input, there might be a problem with the connection";
289
+ return;
290
+ }
291
+
292
+ //Parse the xml file with php4 Dom parser.
293
+ $xml_doc=domxml_open_mem($xml_file);
294
+
295
+ //domxml_open_mem should Return object.
296
+ if ((!is_object($xml_doc)) && !$xml_doc)
297
+ {
298
+ $this->LastOperationSucceeded = false;
299
+ $this->LastOperationErrorMessage = "Error : could not parse XML input, there might be a problem with the connection";
300
+ return ;
301
+ }
302
+
303
+ //Get the Root Element.
304
+ $xml_root=$xml_doc->document_element();
305
+
306
+ //Check the ErrorOccured node in the xml file
307
+
308
+ if(!$this->CheckForAPIErrors($xml_root))
309
+ {
310
+ return ;
311
+ }
312
+
313
+ return $this->GetReturnValue($xml_root,$ReturnValue);
314
+ }
315
+
316
+ //return value by xml type
317
+ function GetReturnValue($xml_root,$ReturnValue)
318
+ {
319
+ switch ($ReturnValue)
320
+ {
321
+ case "QwiserSearchResults":
322
+ return (new QwiserSearchResults($xml_root));
323
+ break;
324
+ case "String":
325
+ return $this->SimpleStringParser($xml_root);
326
+ break;
327
+ case "QwiserQuestions":
328
+ return (new QwiserQuestions(current($xml_root->get_elements_by_tagname("Questions"))));
329
+ break;
330
+ case "QwiserProductAnswers":
331
+ return (new QwiserProductAnswers(current($xml_root->get_elements_by_tagname("ProductAnswers"))));
332
+ break;
333
+ case "QwiserProductFields":
334
+ print_r($xml_root) ;
335
+ return (new QwiserProductFields(current($xml_root->get_elements_by_tagname("ProductFields"))));
336
+ break;
337
+ case "QwiserSearchPath":
338
+ return (new QwiserSearchPath(current($xml_root->get_elements_by_tagname("SearchPath"))));
339
+ break;
340
+ case "QwiserAnswers":
341
+ return (new QwiserAnswers(current($xml_root->get_elements_by_tagname("Answers"))));
342
+ break;
343
+ case "QwiserSimpleStringCollection":
344
+ return GetQwiserSimpleStringCollection(current($xml_root->get_elements_by_tagname("QwiserSimpleStringCollection")));
345
+ break;
346
+ case "QwiserSimpleStringCollection":
347
+ return new QwiserProductsMetaData(current($xml_root->get_elements_by_tagname("Products")));
348
+ break;
349
+ }
350
+ }
351
+
352
+ //Checks the error node
353
+ function CheckForAPIErrors($xml_root)
354
+ {
355
+
356
+ $ErrorNode = current($xml_root->get_elements_by_tagname("QwiserError"));
357
+ if(is_object($ErrorNode))
358
+ {
359
+ $MethodName = $ErrorNode->get_attribute("MethodName");
360
+ if($MethodName=="")
361
+ {
362
+ return true;
363
+ }
364
+ $ErrorMessage = $ErrorNode->get_attribute("ErrorMessage");
365
+ $this->LastOperationErrorMessage = "Error: MethodName=".$MethodName." ErrorMessage=".$ErrorMessage;
366
+
367
+ $this->LastOperationSucceeded = false;
368
+
369
+ }
370
+ else
371
+ {
372
+ $this->LastOperationErrorMessage = "Error: ".$xml_root->get_content();
373
+ }
374
+ return false;
375
+ }
376
+
377
+ //returns the "ReturnValue" node as string
378
+ function SimpleStringParser($xml_root)
379
+ {
380
+ $StringValue = current($xml_root->get_elements_by_tagname("ReturnValue"));
381
+ return $StringValue->get_content();
382
+ }
383
+ }
384
+
385
+ //Global function: Returns Array of strings from Array of nodes contents.
386
+ function GetQwiserSimpleStringCollection ($xml_node)
387
+ {
388
+ $xml_nodes = $xml_node->child_nodes();
389
+ $xml_nodes = getDomElements($xml_nodes);
390
+ $arr = array();
391
+ foreach($xml_nodes as $node)
392
+ {
393
+ $arr[] = $node->get_content();
394
+ }
395
+ return $arr;
396
+ }
397
+
398
+ //Global function: Returns hash of value .
399
+ function GetQwiserSimpleStringDictionary($xml_node)
400
+ {
401
+ $xml_nodes = $xml_node->child_nodes();
402
+ $xml_nodes = getDomElements($xml_nodes);
403
+ $arr = array();
404
+ foreach($xml_nodes as $node)
405
+ {
406
+ $arr[$node->get_attribute("name")] = $node->get_attribute("value");
407
+ }
408
+ return $arr;
409
+ }
410
+
411
+ //Global function: Returns Array of only DomElments
412
+ function getDomElements($element)
413
+ {
414
+ $p=0;
415
+ $new_element = array();
416
+ foreach ($element as $value)
417
+ {
418
+ if($value->node_type()==1)
419
+ {
420
+ $new_element[$p]=$value;
421
+ $p++;
422
+ }
423
+ }
424
+ return $new_element;
425
+ }
426
+
427
+
428
+ ?>
app/code/community/LetsSyncroLLC/Oct8ne/Helper/Search/CelebrosAPI/QwiserSearchPath.php ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class QwiserSearchPath
3
+ {
4
+ var $Count = 0;
5
+ var $Items;
6
+
7
+ Function QwiserSearchPath($xml_SearchPath)
8
+ {
9
+ if(is_object($xml_SearchPath))
10
+ {
11
+ $xml_SearchPathNodes = $xml_SearchPath->child_nodes();
12
+ $xml_SearchPathNodes = getDomElements($xml_SearchPathNodes);
13
+ $this->Count = count($xml_SearchPathNodes);
14
+
15
+ for ($i = 0 ; $i <= $this->Count - 1;$i++)
16
+ {
17
+ $SearchPathNode = $xml_SearchPathNodes[$i];
18
+ $this->Items[$i] = new QwiserSearchPathEntry($SearchPathNode);
19
+ }
20
+ }
21
+ }
22
+ }
23
+ ?>
app/code/community/LetsSyncroLLC/Oct8ne/Helper/Search/CelebrosAPI/QwiserSearchPathEntry.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class QwiserSearchPathEntry
3
+ {
4
+ var $AnswerIndex;
5
+ var $Answers;
6
+ var $QuestionId;
7
+
8
+ Function QwiserSearchPathEntry($EntryNode)
9
+ {
10
+ if(is_object($EntryNode))
11
+ {
12
+ $this->AnswerIndex = $EntryNode->get_attribute("AnswerIndex");
13
+ $this->QuestionId = $EntryNode->get_attribute("QuestionID");
14
+ $this->Answers = new QwiserAnswers(current(getDomElements($EntryNode->child_nodes())));
15
+ }
16
+ }
17
+ }
18
+ ?>
app/code/community/LetsSyncroLLC/Oct8ne/Helper/Search/CelebrosAPI/QwiserSearchResults.php ADDED
@@ -0,0 +1,98 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class QwiserSearchResults
3
+ {
4
+ var $xml_root;
5
+ var $QwiserSearchResults;
6
+ var $SearchInformation;
7
+ var $Questions;
8
+ var $SearchPath;
9
+ var $Products;
10
+ var $QueryConcepts;
11
+ var $SpellerInformation ;
12
+ var $RelatedSearches;
13
+ var $SpecialCasesDetectedInThisSearch;
14
+
15
+ Function QwiserSearchResults($root)
16
+ {
17
+ $this->xml_root = $root;
18
+ $this->QwiserSearchResults = current($this->xml_root->get_elements_by_tagname("QwiserSearchResults"));
19
+
20
+ $this->SearchInformation = NEW SearchInformation(current($this->xml_root->get_elements_by_tagname("SearchInformation")));
21
+ $this->Questions = NEW QwiserQuestions(current($this->xml_root->get_elements_by_tagname("Questions")));
22
+ $this->SearchPath = NEW QwiserSearchPath(current($this->xml_root->get_elements_by_tagname("SearchPath")));
23
+ $this->Products = NEW QwiserProducts(current($this->xml_root->get_elements_by_tagname("Products")));
24
+ $this->QueryConcepts = NEW QwiserConcepts(current($this->xml_root->get_elements_by_tagname("QueryConcepts")));
25
+ $this->SpellerInformation = NEW QwiserSpellerInformation(current($this->xml_root->get_elements_by_tagname("SpellerInformation")));
26
+ $this->RelatedSearches = GetQwiserSimpleStringCollection(current($this->xml_root->get_elements_by_tagname("RelatedSearches")));
27
+ $this->SpecialCasesDetectedInThisSearch = current($this->xml_root->get_elements_by_tagname("SpecialCasesDetectedInThisSearch"));
28
+ }
29
+
30
+ Function GetExactMatchFound()
31
+ {
32
+ return $this->QwiserSearchResults->get_attribute("ExactMatchFound");
33
+ }
34
+
35
+ Function GetLogHandle()
36
+ {
37
+ return $this->QwiserSearchResults->get_attribute("LogHandle");
38
+ }
39
+
40
+ Function GetSearchHandle()
41
+ {
42
+ return $this->QwiserSearchResults->get_attribute("SearchHandle");
43
+ }
44
+
45
+ Function GetMaxMatchClassFound()
46
+ {
47
+ return $this->QwiserSearchResults->get_attribute("MaxMatchClassFound");
48
+ }
49
+
50
+ Function GetMinMatchClassFound()
51
+ {
52
+ return $this->QwiserSearchResults->get_attribute("MinMatchClassFound");
53
+ }
54
+
55
+ Function GetRecommendedMessage()
56
+ {
57
+ return $this->QwiserSearchResults->get_attribute("RecommendedMessage");
58
+ }
59
+
60
+ Function GetRedirectionUrl()
61
+ {
62
+ return $this->QwiserSearchResults->get_attribute("RedirectionUrl");
63
+ }
64
+
65
+ Function GetRelevantProductsCount()
66
+ {
67
+ return $this->QwiserSearchResults->get_attribute("RelevantProductsCount");
68
+ }
69
+
70
+ Function GetSearchDataVersion()
71
+ {
72
+ return $this->QwiserSearchResults->get_attribute("SearchDataVersion");
73
+ }
74
+
75
+ Function GetSearchEngineTimeDuration()
76
+ {
77
+ return $this->QwiserSearchResults->get_attribute("SearchEngineTimeDuration");
78
+ }
79
+
80
+ Function GetSearchTimeDuration()
81
+ {
82
+ return $this->QwiserSearchResults->get_attribute("SearchTimeDuration");
83
+ }
84
+
85
+ Function GetSearchStatus()
86
+ {
87
+ return $this->QwiserSearchResults->get_attribute("SearchStatus");
88
+ }
89
+
90
+ Function GetSpecialCasesDetectedInThisSearch()
91
+ {
92
+ return $this->SpecialCasesDetectedInThisSearch->get_elements_by_tagname("Value");
93
+ }
94
+
95
+ }
96
+
97
+
98
+ ?>
app/code/community/LetsSyncroLLC/Oct8ne/Helper/Search/CelebrosAPI/QwiserSpellerInformation.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class QwiserSpellerInformation
3
+ {
4
+ var $AdditionalSuggestions;
5
+ var $SpellerAutoCorrection;
6
+ var $SpellingErrorDetected = "false";
7
+
8
+ function QwiserSpellerInformation($xml_SpellerInformation)
9
+ {
10
+ if(is_object($xml_SpellerInformation))
11
+ {
12
+ $this->SpellingErrorDetected = $xml_SpellerInformation->get_attribute("SpellingErrorDetected");
13
+ $this->SpellerAutoCorrection = $xml_SpellerInformation->get_attribute("SpellerAutoCorrection");
14
+ $this->AdditionalSuggestions = GetQwiserSimpleStringCollection(current(getDomElements($xml_SpellerInformation->child_nodes())));
15
+ }
16
+ }
17
+ }
18
+ ?>
app/code/community/LetsSyncroLLC/Oct8ne/Helper/Search/CelebrosAPI/SearchInformation.php ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class SearchInformation
3
+ {
4
+ var $Query;
5
+ var $OriginalQuery;
6
+ var $SearchProfileName;
7
+ var $PriceFieldName;
8
+ var $NumberOfPages;
9
+ var $CurrentPage;
10
+ var $PageSize;
11
+ var $IsDefaultPageSize;
12
+ var $IsDefaultSearchProfileName;
13
+ var $SkuSearchOccured;
14
+ var $DeadEndOccurred;
15
+ var $FirstQuestionId;
16
+ var $SessionId;
17
+ VAR $Stage;
18
+ var $SortingOptions;
19
+
20
+
21
+ fUNCTION SearchInformation($xml_SearchInformation)
22
+ {
23
+ if(is_object($xml_SearchInformation))
24
+ {
25
+ $this->Query = $xml_SearchInformation->get_attribute("Query");
26
+ $this->OriginalQuery = $xml_SearchInformation->get_attribute("OriginalQuery");
27
+ $this->SearchProfileName = $xml_SearchInformation->get_attribute("SearchProfileName");
28
+ $this->PriceFieldName = $xml_SearchInformation->get_attribute("PriceFieldName");
29
+ $this->NumberOfPages = $xml_SearchInformation->get_attribute("NumberOfPages");
30
+ $this->CurrentPage = $xml_SearchInformation->get_attribute("CurrentPage");
31
+ $this->PageSize = $xml_SearchInformation->get_attribute("PageSize");
32
+ $this->IsDefaultPageSize = $xml_SearchInformation->get_attribute("IsDefaultPageSize");
33
+ $this->SkuSearchOccured = $xml_SearchInformation->get_attribute("SkuSearchOccured");
34
+ $this->DeadEndOccurred = $xml_SearchInformation->get_attribute("DeadEndOccurred");
35
+ $this->FirstQuestionId = $xml_SearchInformation->get_attribute("FirstQuestionId");
36
+ $this->SessionId = $xml_SearchInformation->get_attribute("SessionId");
37
+ $this->Stage = $xml_SearchInformation->get_attribute("Stage");
38
+
39
+ $this->SortingOptions = new SortingOptions(current($xml_SearchInformation->get_elements_by_tagname("SortingOptions")));
40
+ }
41
+ }
42
+ }
43
+
44
+ ?>
app/code/community/LetsSyncroLLC/Oct8ne/Helper/Search/CelebrosAPI/SortingOptions.php ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ class SortingOptions
3
+ {
4
+ var $Ascending;
5
+ var $FieldName;
6
+ var $NumericSort;
7
+ var $Method;
8
+
9
+ Function SortingOptions($xml_SortingOptions)
10
+ {
11
+ if(is_object($xml_SortingOptions))
12
+ {
13
+ $this->Ascending = $xml_SortingOptions->get_attribute("Ascending");
14
+ $this->FieldName = $xml_SortingOptions->get_attribute("FieldName");
15
+ $this->NumericSort = $xml_SortingOptions->get_attribute("NumericSort");
16
+ $this->Method = $xml_SortingOptions->get_attribute("Method");
17
+ }
18
+ }
19
+ }
20
+ ?>
app/code/community/LetsSyncroLLC/Oct8ne/Helper/Search/CelebrosAPI/domxml-php4-to-php5.php ADDED
@@ -0,0 +1,316 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ Requires PHP5, uses built-in DOM extension.
4
+ To be used in PHP4 scripts using DOMXML extension.
5
+ Allows PHP4/DOMXML scripts to run on PHP5/DOM.
6
+ (Requires PHP5/XSL extension for domxml_xslt functions)
7
+
8
+ Typical use:
9
+ {
10
+ if (version_compare(PHP_VERSION,'5','>='))
11
+ require_once('domxml-php4-to-php5.php');
12
+ }
13
+ */
14
+
15
+ function domxml_new_doc($version) {return new php4DOMDocument('');}
16
+ function domxml_open_file($filename) {return new php4DOMDocument($filename);}
17
+ function domxml_open_mem($str)
18
+ {
19
+ $dom=new php4DOMDocument('');
20
+ $dom->myDOMNode->loadXML($str);
21
+ return $dom;
22
+ }
23
+ function html_doc($html_doc,$from_file=false)
24
+ {
25
+ $dom=new php4DOMDocument('');
26
+ if ($from_file) $dom->myDOMNode->loadHTMLFile($html_doc);
27
+ else $dom->myDOMNode->loadHTML($html_doc);
28
+ return $dom;
29
+ }
30
+ function html_doc_file($filename) {return html_doc($filename,true);}
31
+ function xpath_eval($xpath_context,$eval_str,$contextnode=null) {return $xpath_context->xpath_eval($eval_str,$contextnode);}
32
+ function xpath_new_context($dom_document) {return new php4DOMXPath($dom_document);}
33
+ function xpath_register_ns($xpath_context,$prefix,$namespaceURI) {return $xpath_context->myDOMXPath->registerNamespace($prefix,$namespaceURI);}
34
+
35
+ class php4DOMAttr extends php4DOMNode
36
+ {
37
+ function php4DOMAttr($aDOMAttr) {$this->myDOMNode=$aDOMAttr;}
38
+ function name() {return $this->myDOMNode->name;}
39
+ function set_value($content) {return $this->myDOMNode->value=$content;}
40
+ function specified() {return $this->myDOMNode->specified;}
41
+ function value() {return $this->myDOMNode->value;}
42
+ }
43
+
44
+ class php4DOMDocument extends php4DOMNode
45
+ {
46
+ function php4DOMDocument($filename='')
47
+ {
48
+ $this->myDOMNode=new DOMDocument();
49
+ $this->myOwnerDocument=$this;
50
+ if ($filename!='') $this->myDOMNode->load($filename);
51
+ }
52
+ function add_root($name)
53
+ {
54
+ if ($this->myDOMNode->hasChildNodes()) $this->myDOMNode->removeChild($this->myDOMNode->firstChild);
55
+ return new php4DOMElement($this->myDOMNode->appendChild($this->myDOMNode->createElement($name)),$this->myOwnerDocument);
56
+ }
57
+ function create_attribute($name,$value)
58
+ {
59
+ $myAttr=$this->myDOMNode->createAttribute($name);
60
+ $myAttr->value=$value;
61
+ return new php4DOMAttr($myAttr,$this);
62
+ }
63
+ function create_cdata_section($content) {return new php4DOMNode($this->myDOMNode->createCDATASection($content),$this);}
64
+ function create_comment($data) {return new php4DOMNode($this->myDOMNode->createComment($data),$this);}
65
+ function create_element($name) {return new php4DOMElement($this->myDOMNode->createElement($name),$this);}
66
+ function create_text_node($content) {return new php4DOMText($this->myDOMNode->createTextNode($content),$this);}
67
+ function document_element() {return parent::_newDOMElement($this->myDOMNode->documentElement,$this);}
68
+ function dump_file($filename,$compressionmode=false,$format=false)
69
+ {
70
+ $format0=$this->myDOMNode->formatOutput;
71
+ $this->myDOMNode->formatOutput=$format;
72
+ $res=$this->myDOMNode->save($filename);
73
+ $this->myDOMNode->formatOutput=$format0;
74
+ return $res;
75
+ }
76
+ function dump_mem($format=false,$encoding=false)
77
+ {
78
+ $format0=$this->myDOMNode->formatOutput;
79
+ $this->myDOMNode->formatOutput=$format;
80
+ $encoding0=$this->myDOMNode->encoding;
81
+ if ($encoding) $this->myDOMNode->encoding=$encoding;
82
+ $dump=$this->myDOMNode->saveXML();
83
+ $this->myDOMNode->formatOutput=$format0;
84
+ if ($encoding) $this->myDOMNode->encoding= $encoding0=='' ? 'UTF-8' : $encoding0; //UTF-8 is XML default encoding
85
+ return $dump;
86
+ }
87
+ function dump_node($node) {return $this->myDOMNode->saveXML($node->myDOMNode);}
88
+ function free()
89
+ {
90
+ if ($this->myDOMNode->hasChildNodes()) $this->myDOMNode->removeChild($this->myDOMNode->firstChild);
91
+ $this->myDOMNode=null;
92
+ $this->myOwnerDocument=null;
93
+ }
94
+ function get_element_by_id($id) {return parent::_newDOMElement($this->myDOMNode->getElementById($id),$this);}
95
+ function get_elements_by_tagname($name)
96
+ {
97
+ $myDOMNodeList=$this->myDOMNode->getElementsByTagName($name);
98
+ $nodeSet=array();
99
+ $i=0;
100
+ if (isset($myDOMNodeList))
101
+ while ($node=$myDOMNodeList->item($i++)) $nodeSet[]=new php4DOMElement($node,$this);
102
+ return $nodeSet;
103
+ }
104
+ function html_dump_mem() {return $this->myDOMNode->saveHTML();}
105
+ function root() {return parent::_newDOMElement($this->myDOMNode->documentElement,$this);}
106
+ function xpath_new_context() {return new php4DOMXPath($this);}
107
+ }
108
+
109
+ class php4DOMElement extends php4DOMNode
110
+ {
111
+ function get_attribute($name) {return $this->myDOMNode->getAttribute($name);}
112
+ function get_elements_by_tagname($name)
113
+ {
114
+ $myDOMNodeList=$this->myDOMNode->getElementsByTagName($name);
115
+ $nodeSet=array();
116
+ $i=0;
117
+ if (isset($myDOMNodeList))
118
+ while ($node=$myDOMNodeList->item($i++)) $nodeSet[]=new php4DOMElement($node,$this->myOwnerDocument);
119
+ return $nodeSet;
120
+ }
121
+ function has_attribute($name) {return $this->myDOMNode->hasAttribute($name);}
122
+ function remove_attribute($name) {return $this->myDOMNode->removeAttribute($name);}
123
+ function set_attribute($name,$value) {return $this->myDOMNode->setAttribute($name,$value);}
124
+ function set_name($name)
125
+ {
126
+ if ($this->myDOMNode->prefix=='') $newNode=$this->myDOMNode->ownerDocument->createElement($name);
127
+ else $newNode=$this->myDOMNode->ownerDocument->createElementNS($this->myDOMNode->namespaceURI,$this->myDOMNode->prefix.':'.$name);
128
+ $myDOMNodeList=$this->myDOMNode->attributes;
129
+ $i=0;
130
+ if (isset($myDOMNodeList))
131
+ while ($node=$myDOMNodeList->item($i++))
132
+ if ($node->namespaceURI=='') $newNode->setAttribute($node->name,$node->value);
133
+ else $newNode->setAttributeNS($node->namespaceURI,$node->nodeName,$node->value);
134
+ $myDOMNodeList=$this->myDOMNode->childNodes;
135
+ if (isset($myDOMNodeList))
136
+ while ($node=$myDOMNodeList->item(0)) $newNode->appendChild($node);
137
+ $this->myDOMNode->parentNode->replaceChild($newNode,$this->myDOMNode);
138
+ $this->myDOMNode=$newNode;
139
+ return true;
140
+ }
141
+ function tagname() {return $this->myDOMNode->tagName;}
142
+ }
143
+
144
+ class php4DOMNode
145
+ {
146
+ var $myDOMNode;
147
+ var $myOwnerDocument;
148
+ function php4DOMNode($aDomNode,$aOwnerDocument)
149
+ {
150
+ $this->myDOMNode=$aDomNode;
151
+ $this->myOwnerDocument=$aOwnerDocument;
152
+ }
153
+ function __get($name)
154
+ {
155
+ switch ($name)
156
+ {
157
+ case 'type': return $this->myDOMNode->nodeType;
158
+ case 'tagname': return $this->myDOMNode->tagName;
159
+ case 'content': return $this->myDOMNode->textContent;
160
+ case 'name': return $this->myDOMNode->name;
161
+ case 'value': return $this->myDOMNode->value;
162
+ default:
163
+ $myErrors=debug_backtrace();
164
+ trigger_error('Undefined property: '.get_class($this).'::$'.$name.' ['.$myErrors[0]['file'].':'.$myErrors[0]['line'].']',E_USER_NOTICE);
165
+ return false;
166
+ }
167
+ }
168
+ function append_child($newnode) {return self::_newDOMElement($this->myDOMNode->appendChild($this->_importNode($newnode)),$this->myOwnerDocument);}
169
+ function append_sibling($newnode) {return self::_newDOMElement($this->myDOMNode->parentNode->appendChild($this->_importNode($newnode)),$this->myOwnerDocument);}
170
+ function attributes()
171
+ {
172
+ $myDOMNodeList=$this->myDOMNode->attributes;
173
+ $nodeSet=array();
174
+ $i=0;
175
+ if (isset($myDOMNodeList))
176
+ while ($node=$myDOMNodeList->item($i++)) $nodeSet[]=new php4DOMAttr($node,$this->myOwnerDocument);
177
+ return $nodeSet;
178
+ }
179
+ function child_nodes()
180
+ {
181
+ $myDOMNodeList=$this->myDOMNode->childNodes;
182
+ $nodeSet=array();
183
+ $i=0;
184
+ if (isset($myDOMNodeList))
185
+ while ($node=$myDOMNodeList->item($i++)) $nodeSet[]=self::_newDOMElement($node,$this->myOwnerDocument);
186
+ return $nodeSet;
187
+ }
188
+ function children() {return $this->child_nodes();}
189
+ function clone_node($deep=false) {return self::_newDOMElement($this->myDOMNode->cloneNode($deep),$this->myOwnerDocument);}
190
+ function dump_node($node) {return $node==null ? $this->myOwnerDocument->myDOMNode->saveXML($this->myDOMNode) : $this->myOwnerDocument->myDOMNode->saveXML($node->myDOMNode);}
191
+ function first_child() {return self::_newDOMElement($this->myDOMNode->firstChild,$this->myOwnerDocument);}
192
+ function get_content() {return $this->myDOMNode->textContent;}
193
+ function has_attributes() {return $this->myDOMNode->hasAttributes();}
194
+ function has_child_nodes() {return $this->myDOMNode->hasChildNodes();}
195
+ function insert_before($newnode,$refnode) {return self::_newDOMElement($this->myDOMNode->insertBefore($newnode->myDOMNode,$refnode->myDOMNode),$this->myOwnerDocument);}
196
+ function is_blank_node() {return ($this->myDOMNode->nodeType==XML_TEXT_NODE)&&preg_match('%^\s*$%',$this->myDOMNode->nodeValue);}
197
+ function last_child() {return self::_newDOMElement($this->myDOMNode->lastChild,$this->myOwnerDocument);}
198
+ function new_child($name,$content)
199
+ {
200
+ $mySubNode=$this->myDOMNode->ownerDocument->createElement($name);
201
+ $mySubNode->appendChild($this->myDOMNode->ownerDocument->createTextNode(html_entity_decode($content,ENT_QUOTES)));
202
+ $this->myDOMNode->appendChild($mySubNode);
203
+ return new php4DOMElement($mySubNode,$this->myOwnerDocument);
204
+ }
205
+ function next_sibling() {return self::_newDOMElement($this->myDOMNode->nextSibling,$this->myOwnerDocument);}
206
+ function node_name() {return ($this->myDOMNode->nodeType==XML_ELEMENT_NODE) ? $this->myDOMNode->localName : $this->myDOMNode->nodeName;} //avoid namespace prefix for DOMElement
207
+ function node_type() {return $this->myDOMNode->nodeType;}
208
+ function node_value() {return $this->myDOMNode->nodeValue;}
209
+ function owner_document() {return $this->myOwnerDocument;}
210
+ function parent_node() {return self::_newDOMElement($this->myDOMNode->parentNode,$this->myOwnerDocument);}
211
+ function prefix() {return $this->myDOMNode->prefix;}
212
+ function previous_sibling() {return self::_newDOMElement($this->myDOMNode->previousSibling,$this->myOwnerDocument);}
213
+ function remove_child($oldchild) {return self::_newDOMElement($this->myDOMNode->removeChild($oldchild->myDOMNode),$this->myOwnerDocument);}
214
+ function replace_child($oldnode,$newnode) {return self::_newDOMElement($this->myDOMNode->replaceChild($oldnode->myDOMNode,$this->_importNode($newnode)),$this->myOwnerDocument);}
215
+ function set_content($text) {return $this->myDOMNode->appendChild($this->myDOMNode->ownerDocument->createTextNode($text));}
216
+ //function set_name($name) {return $this->myOwnerDocument->renameNode($this->myDOMNode,$this->myDOMNode->namespaceURI,$name);}
217
+ protected function _importNode($newnode) {return $this->myOwnerDocument===$newnode->myOwnerDocument ? $newnode->myDOMNode : $this->myOwnerDocument->myDOMNode->importNode($newnode->myDOMNode,true);} //to import DOMNode from another DOMDocument
218
+ static function _newDOMElement($aDOMNode,$aOwnerDocument)
219
+ {//to check the PHP5 DOMNode before creating a new associated PHP4 DOMNode wrapper
220
+ if ($aDOMNode==null) return null;
221
+ switch ($aDOMNode->nodeType)
222
+ {
223
+ case XML_ELEMENT_NODE: return new php4DOMElement($aDOMNode,$aOwnerDocument);
224
+ case XML_TEXT_NODE: return new php4DOMText($aDOMNode,$aOwnerDocument);
225
+ case XML_ATTRIBUTE_NODE: return new php4DOMAttr($aDOMNode,$aOwnerDocument);
226
+ default: return new php4DOMNode($aDOMNode,$aOwnerDocument);
227
+ }
228
+ }
229
+ }
230
+
231
+ class php4DOMText extends php4DOMNode
232
+ {
233
+ function __get($name)
234
+ {
235
+ if ($name=='tagname') return '#text';
236
+ else return parent::__get($name);
237
+ }
238
+ function tagname() {return '#text';}
239
+ }
240
+
241
+ if (!defined('XPATH_NODESET'))
242
+ {
243
+ define('XPATH_UNDEFINED',0);
244
+ define('XPATH_NODESET',1);
245
+ /*define('XPATH_BOOLEAN',2);
246
+ define('XPATH_NUMBER',3);
247
+ define('XPATH_STRING',4);
248
+ define('XPATH_POINT',5);
249
+ define('XPATH_RANGE',6);
250
+ define('XPATH_LOCATIONSET',7);
251
+ define('XPATH_USERS',8);
252
+ define('XPATH_XSLT_TREE',9);*/
253
+ }
254
+
255
+ class php4DOMNodelist
256
+ {//TODO: To be updated for PHP/5.1 to allow XPath boolean expressions etc. DOMXPath->evaluate()
257
+ var $myDOMNodelist;
258
+ var $nodeset;
259
+ var $type;
260
+ function php4DOMNodelist($aDOMNodelist,$aOwnerDocument)
261
+ {
262
+ $this->myDOMNodelist=$aDOMNodelist;
263
+ $this->nodeset=array();
264
+ $i=0;
265
+ if (isset($this->myDOMNodelist))
266
+ {
267
+ $this->type=XPATH_NODESET;
268
+ while ($node=$this->myDOMNodelist->item($i++)) $this->nodeset[]=php4DOMNode::_newDOMElement($node,$aOwnerDocument);
269
+ }
270
+ else $this->type=XPATH_UNDEFINED;
271
+ }
272
+ }
273
+
274
+ class php4DOMXPath
275
+ {
276
+ var $myDOMXPath;
277
+ var $myOwnerDocument;
278
+ function php4DOMXPath($dom_document)
279
+ {
280
+ $this->myOwnerDocument=$dom_document;
281
+ $this->myDOMXPath=new DOMXPath($dom_document->myDOMNode);
282
+ }
283
+ function xpath_eval($eval_str,$contextnode=null) {return isset($contextnode) ? new php4DOMNodelist($this->myDOMXPath->query($eval_str,$contextnode->myDOMNode),$this->myOwnerDocument) : new php4DOMNodelist($this->myDOMXPath->query($eval_str),$this->myOwnerDocument);}
284
+ function xpath_register_ns($prefix,$namespaceURI) {return $this->myDOMXPath->registerNamespace($prefix,$namespaceURI);}
285
+ }
286
+
287
+ if (extension_loaded('xsl'))
288
+ {//See also: http://alexandre.alapetite.net/doc-alex/xslt-php4-php5/
289
+ function domxml_xslt_stylesheet($xslstring) {return new php4DomXsltStylesheet(DOMDocument::loadXML($xslstring));}
290
+ function domxml_xslt_stylesheet_doc($dom_document) {return new php4DomXsltStylesheet($dom_document);}
291
+ function domxml_xslt_stylesheet_file($xslfile) {return new php4DomXsltStylesheet(DOMDocument::load($xslfile));}
292
+ class php4DomXsltStylesheet
293
+ {
294
+ var $myxsltProcessor;
295
+ function php4DomXsltStylesheet($dom_document)
296
+ {
297
+ $this->myxsltProcessor=new xsltProcessor();
298
+ $this->myxsltProcessor->importStyleSheet($dom_document);
299
+ }
300
+ function process($dom_document,$xslt_parameters=array(),$param_is_xpath=false)
301
+ {
302
+ foreach ($xslt_parameters as $param=>$value) $this->myxsltProcessor->setParameter('',$param,$value);
303
+ $myphp4DOMDocument=new php4DOMDocument();
304
+ $myphp4DOMDocument->myDOMNode=$this->myxsltProcessor->transformToDoc($dom_document->myDOMNode);
305
+ return $myphp4DOMDocument;
306
+ }
307
+ function result_dump_file($dom_document,$filename)
308
+ {
309
+ $html=$dom_document->myDOMNode->saveHTML();
310
+ file_put_contents($filename,$html);
311
+ return $html;
312
+ }
313
+ function result_dump_mem($dom_document) {return $dom_document->myDOMNode->saveHTML();}
314
+ }
315
+ }
316
+ ?>
app/code/community/LetsSyncroLLC/Oct8ne/Helper/Search/Sli.php CHANGED
@@ -1,5 +1,11 @@
1
  <?php
2
 
 
 
 
 
 
 
3
  class LetsSyncroLLC_Oct8ne_Helper_Search_Sli extends LetsSyncroLLC_Oct8ne_Helper_Search_Base {
4
 
5
  public function getEngineName() {
@@ -20,8 +26,11 @@ class LetsSyncroLLC_Oct8ne_Helper_Search_Sli extends LetsSyncroLLC_Oct8ne_Helper
20
  return array();
21
  }
22
  $totalSearchResults = $result["result_meta"]["total"];
23
- $attrs_available = $this->getAvailableFilters($result);
24
- $attrs_applied = $this->getResponseAppliedFilter($attrs_available);
 
 
 
25
  $productIds = $this->getProductIds($result);
26
  $this->log("Total {$totalSearchResults}, ids of this page: [" . implode(",", $productIds) . "]");
27
  return $productIds;
@@ -190,19 +199,14 @@ class LetsSyncroLLC_Oct8ne_Helper_Search_Sli extends LetsSyncroLLC_Oct8ne_Helper
190
  }
191
 
192
  private function getFacets() {
193
- $request = $this->getRequest();
194
- $queryStringParams = array_keys($_GET);
195
- $facet = "";
196
- foreach ($queryStringParams as $param) {
197
- // Ignore standard query standard params
198
- if (substr($param, 0, 1) == '_' || $param == 'callback' || $param == 'search' || $param == 'store' || $param == 'orderby' || $param == 'dir' || $param == 'page' || $param == 'pageSize') {
199
- continue;
200
- }
201
 
202
- // If we get here, the param is a facet
203
- $value = $request->getParam($param);
204
- if (!is_null($value) && trim($value) != '') {
205
- $facet .= $param . ':' . $value . ' ';
 
 
 
206
  }
207
  }
208
  return trim($facet);
1
  <?php
2
 
3
+ /* SLI Search engine adapter
4
+ *
5
+ * Parameter: host (SLI endpoint)
6
+ *
7
+ */
8
+
9
  class LetsSyncroLLC_Oct8ne_Helper_Search_Sli extends LetsSyncroLLC_Oct8ne_Helper_Search_Base {
10
 
11
  public function getEngineName() {
26
  return array();
27
  }
28
  $totalSearchResults = $result["result_meta"]["total"];
29
+
30
+ $allAvailableFilters = $this->getAvailableFilters($result);
31
+ $attrs_applied = $this->getResponseAppliedFilter($allAvailableFilters);
32
+ $attrs_available = $this->getAvailableButNotAppliedFilters($attrs_applied, $allAvailableFilters);
33
+
34
  $productIds = $this->getProductIds($result);
35
  $this->log("Total {$totalSearchResults}, ids of this page: [" . implode(",", $productIds) . "]");
36
  return $productIds;
199
  }
200
 
201
  private function getFacets() {
 
 
 
 
 
 
 
 
202
 
203
+ $appliedFilters = $this->getAppliedFilters();
204
+ if ($appliedFilters) {
205
+ $facet = "";
206
+ foreach ($appliedFilters as $param => $value) {
207
+ if (!is_null($value) && trim($value) != '') {
208
+ $facet .= $param . ':' . $value . ' ';
209
+ }
210
  }
211
  }
212
  return trim($facet);
app/code/community/LetsSyncroLLC/Oct8ne/Helper/Search/Solr.php ADDED
@@ -0,0 +1,466 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /* Solr Search engine adapter
4
+ * Parameters
5
+ * - host: Solr endpoint
6
+ * - username: username (optional)
7
+ * - password: password (optional)
8
+ * - id_field: name of id field
9
+ * - name_field: name of product name field (used for sorting)
10
+ * - price_field: name of price field (used for sorting and filtering)
11
+ * - query_field: name of the field where the text search is performed
12
+ * - additional_query_params: additional criteria to be added to the search expression
13
+ * - categories_field: name of the field having the array of categories the product belongs to
14
+ * - related_method: method to get the related products (name|name-reverse|categories|self)
15
+ * - facet_fields: comma separated list of filter fields
16
+ * - price_range: {start},{end},{gap} Example: 0,1000,200 (group prices from 0 to 1000 in ranges of 200)
17
+ * - http_verb: HTTP verb to use in requests (get|post). By default, "get".
18
+ *
19
+ * Example:
20
+ host=http://dev.binaryanvil.net:8080/solr;
21
+ id_field=id;
22
+ additional_query_params=in_stock:true AND store_id:1;
23
+ query_field=fulltext_1_en;
24
+ name_field=attr_sort_name_en;
25
+ price_field=price_0_1;
26
+ related_method=name;
27
+ categories_field=category_ids;
28
+ facet_fields=color_family,size;
29
+ price_range=0,1000,100;
30
+ http_verb=get;
31
+ */
32
+
33
+ class LetsSyncroLLC_Oct8ne_Helper_Search_Solr extends LetsSyncroLLC_Oct8ne_Helper_Search_Base {
34
+
35
+ const PRICE_PARAM_NAME = "price-param";
36
+
37
+ public function getEngineName() {
38
+ return "solr";
39
+ }
40
+
41
+ public function isValidSearchCriteria($searchTerm) {
42
+ if (is_null($searchTerm) || strlen($searchTerm) == 0) {
43
+ return false;
44
+ }
45
+ return true;
46
+ }
47
+
48
+ public function search($storeId, $searchTerm, $searchOrder, $searchDir, $page, $pageSize, &$totalSearchResults, &$attrs_applied, &$attrs_available) {
49
+ if (!$this->checkEngineParams()) {
50
+ return array();
51
+ }
52
+
53
+ $this->log("Searching " . $searchTerm);
54
+ $result = $this->executeSolrSearchQuery($searchTerm, NULL, $searchOrder, $searchDir, $page, $pageSize, TRUE /* addFacets */);
55
+ if (is_null($result)) {
56
+ return array();
57
+ }
58
+ $totalSearchResults = $result["response"]["numFound"];
59
+
60
+ $allAvailableFilters = $this->getAvailableFilters($result);
61
+ $attrs_applied = $this->getResponseAppliedFilter($allAvailableFilters);
62
+ $attrs_available = $this->getAvailableButNotAppliedFilters($attrs_applied, $allAvailableFilters);
63
+ $productIds = $this->getProductIds($result);
64
+ $this->log("Total {$totalSearchResults}, ids of this page: [" . implode(",", $productIds) . "]");
65
+ return $productIds;
66
+ }
67
+
68
+ public function getRelatedProductIds($product, $page, $pageSize) {
69
+ if (!$this->checkEngineParams()) {
70
+ return array();
71
+ }
72
+
73
+ if ($relatedMethod == "self") {
74
+ $result = array($product->getId());
75
+ return $result;
76
+ }
77
+
78
+ $pageSize = 30;
79
+ $relatedMethod = strtolower($this->getEngineParam("related_method"));
80
+ if (!$relatedMethod) {
81
+ $relatedMethod = "name";
82
+ }
83
+ $result = NULL;
84
+ if ($relatedMethod == "categories") {
85
+ $categoryIds = $product->getCategoryIds();
86
+ if (!empty($categoryIds)) {
87
+ $result = $this->executeSolrSearchQuery(NULL, $categoryIds, 'score', 'asc', $page, $pageSize, FALSE /* addFacets */);
88
+ }
89
+ $relatedMethod = "name";
90
+ }
91
+ if ($relatedMethod == "name-reverse") {
92
+ $arr = explode(' ', $product->getName());
93
+ $arr = array_reverse($arr);
94
+ $name = implode(' ', $arr);
95
+ $result = $this->executeSolrSearchQuery($name, NULL, 'score', 'desc', $page, $pageSize, FALSE /* addFacets */);
96
+ } else if ($relatedMethod == "name") {
97
+ $name = $product->getName();
98
+ $result = $this->executeSolrSearchQuery($name, NULL, 'score', 'desc', $page, $pageSize, FALSE /* addFacets */);
99
+ }
100
+
101
+ if (is_null($result) || !$result || count($result) == 0) {
102
+ $result = array($product->getId());
103
+ }
104
+
105
+ $productIds = $this->getProductIds($result);
106
+
107
+ return $productIds;
108
+ }
109
+
110
+ private function executeSolrSearchQuery($searchTerm = "", $searchCategories, $searchOrder, $searchDir, $page, $pageSize, $addFacets) {
111
+ if (!function_exists('curl_init')) {
112
+ return NULL;
113
+ }
114
+ $host = $this->normalizeHost($this->getEngineParam("host"));
115
+ if ($page < 1) {
116
+ $page = 1;
117
+ }
118
+ $queryParams = array(
119
+ 'rows' => $pageSize,
120
+ 'start' => $pageSize * ($page - 1),
121
+ 'wt' => 'json',
122
+ 'sort' => $this->getSolrSort($searchOrder, $searchDir),
123
+ 'fl' => $this->getEngineParam("id_field") . ',' . $this->getEngineParam("name_field") . ',' . $this->getEngineParam("price_field"),
124
+ 'facet' => 'true',
125
+ 'facet.mincount' => 1
126
+ );
127
+
128
+ if ($searchCategories) {
129
+ $categoryFieldName = $this->getEngineParam("categories_field");
130
+ if ($categoryFieldName) {
131
+ // Format: q=category_ids:(2+OR+48)
132
+ $queryParams["q"] = $categoryFieldName . ":(" . implode(" OR ", $searchCategories) . ")";
133
+ }
134
+ }
135
+
136
+ $query = $host . '/select?' . http_build_query($queryParams);
137
+
138
+ // Set up query expression
139
+ $queryField = $this->getEngineParam("query_field");
140
+ $q = trim("" . $this->getEngineParam("additional_query_params"));
141
+ if ($q) {
142
+ $q .= " AND ";
143
+ }
144
+ $searchTerm = trim($searchTerm);
145
+ if ($searchTerm) {
146
+ $q .= "(";
147
+ if ($searchTerm[0] == '"' && $searchTerm[strlen($searchTerm) - 1] == '"') {
148
+ $q .= ("(" . $queryField . ":" . $searchTerm . ")");
149
+ } else {
150
+ $q .= $this->generateQueryExpression($queryField, $searchTerm);
151
+ }
152
+ $q .= ")";
153
+ }
154
+ $q = str_replace(" ", "%20", $q);
155
+ $query .= "&q=" . $q;
156
+
157
+ // Set up facets
158
+ if ($addFacets && $this->getEngineParam("facet_fields")) {
159
+ $query = $this->addAllFacetsToQuery($query);
160
+ $query = $this->addCurrentFacetsToQuery($query);
161
+ }
162
+
163
+ // Setup price ranges
164
+ if ($this->getEngineParam("price_range")) {
165
+ $query = $this->addAllPriceRangesToQuery($query);
166
+ }
167
+
168
+ $this->log("Executing query: {$query}");
169
+
170
+ $request = curl_init($query);
171
+
172
+ if($this->getEngineParam("http_verb")=="post") {
173
+ curl_setopt($request, CURLOPT_POST, 1);
174
+ }
175
+ curl_setopt($request, CURLOPT_RETURNTRANSFER, 1);
176
+
177
+ $userName = $this->getEngineParam("username");
178
+ if ($userName) {
179
+ $password = $this->getEngineParam("password");
180
+ if (is_null($password)) {
181
+ $password = "";
182
+ }
183
+ curl_setopt($request, CURLOPT_USERPWD, "$userName:$password");
184
+ }
185
+
186
+ $response = curl_exec($request);
187
+ $err = curl_error($request);
188
+ if (is_null($err) || $err == "") {
189
+ $result = json_decode($response, true);
190
+ if (is_null($result)) {
191
+ $contentType = curl_getinfo($request, CURLINFO_CONTENT_TYPE);
192
+ $msg = "Solr search is not returning valid JSON data, or result is empty. Content-type returned: " . $contentType;
193
+ Mage::log("[Oct8ne] " . $msg);
194
+ $this->log($msg);
195
+ } else {
196
+ $this->log("Query result received");
197
+ }
198
+ } else {
199
+ $this->log("Search error: " . $err);
200
+ $result = NULL;
201
+ }
202
+ curl_close($request);
203
+ return $result;
204
+ }
205
+
206
+ // Add all facets to the query, so
207
+ // the results will include these facets
208
+ private function addAllFacetsToQuery($query) {
209
+ $facetFieldsPrefix = $this->getFacetFieldsPrefix();
210
+ $facetFields = $this->getEngineParam("facet_fields");
211
+ if ($facetFields) {
212
+ $facetFieldsArray = explode(',', $facetFields);
213
+ foreach ($facetFieldsArray as $facet) {
214
+ $query .= "&facet.field=" . $facetFieldsPrefix . trim($facet);
215
+ }
216
+ }
217
+ return $query;
218
+ }
219
+
220
+ // Add the current specified filters to the Solr query
221
+ // using the fq (facet query) parameter
222
+ private function addCurrentFacetsToQuery($query) {
223
+
224
+ $appliedFilters = $this->getAppliedFilters();
225
+ $facetFieldsPrefix = $this->getFacetFieldsPrefix();
226
+ $priceRangeConfig = $this->getPriceRangeConfiguration();
227
+ if ($appliedFilters) {
228
+ foreach ($appliedFilters as $param => $value) {
229
+ if ($param != self::PRICE_PARAM_NAME) { // Price is a special facet and must be handled differently
230
+ $query .= '&fq=' . $facetFieldsPrefix . $param . ':' . urlencode($value);
231
+ } else {
232
+ $min = $value;
233
+ $max = $value + $priceRangeConfig["gap"];
234
+ $query .= '&fq=' . $this->getEngineParam("price_field") . ":[$min%20TO%20$max]";
235
+ }
236
+ }
237
+ }
238
+ return $query;
239
+ }
240
+
241
+ // Adds all price ranges to the query as facet range
242
+ // so the results will include the number of products per each range
243
+ private function addAllPriceRangesToQuery($query) {
244
+ $priceField = $this->getEngineParam("price_field");
245
+ $rangeConfig = $this->getPriceRangeConfiguration();
246
+ if ($rangeConfig) {
247
+ $start = $rangeConfig["start"];
248
+ $end = $rangeConfig["end"];
249
+ $gap = $rangeConfig["gap"];
250
+ $query .= "&facet.range=$priceField&f.$priceField.facet.range.start=$start&f.$priceField.facet.range.end=$end&f.$priceField.facet.range.gap=$gap";
251
+ }
252
+ return $query;
253
+ }
254
+
255
+ private function getProductIds($result) {
256
+ $productIds = array();
257
+ $idField = $this->getEngineParam('id_field');
258
+ if (!$result || !isset($result["response"]) || !isset($result["response"]["docs"]))
259
+ return $productIds;
260
+
261
+ foreach ($result["response"]["docs"] as $product) {
262
+ $productIds[] = $product[$idField];
263
+ }
264
+
265
+ // Uncomment for local testing
266
+ // $productIds = array('906', '875', '874', '554', '553', '552', '551', '549', '399', '398');
267
+
268
+ return $productIds;
269
+ }
270
+
271
+ private function normalizeHost($host) {
272
+ $host = rtrim($host, '/');
273
+ if (!$this->startsWith($host, 'http://') && !!$this->startsWith($host, 'https://')) {
274
+ $host = 'http://' . $host;
275
+ }
276
+ return $host;
277
+ }
278
+
279
+ private function startsWith($str, $subStr) {
280
+ $length = strlen($subStr);
281
+ return (substr($str, 0, $length) === $subStr);
282
+ }
283
+
284
+ private function getSolrSort($searchOrder, $searchDir) {
285
+ $result = "";
286
+ switch ($searchOrder) {
287
+ case "score":
288
+ $result .= "score";
289
+ break;
290
+ case "relevance":
291
+ $result .= "score";
292
+ break;
293
+ case "price":
294
+ $result .= $this->getEngineParam("price_field");
295
+ break;
296
+ case "name":
297
+ $result .= $this->getEngineParam("name_field");
298
+ }
299
+ $result .= ($searchDir == "desc" ? " desc" : " asc" );
300
+ return $result;
301
+ }
302
+
303
+ // Gets all the available filters from the search result
304
+ // using facet_fields and facet_ranges
305
+ private function getAvailableFilters($result) {
306
+ $filters = array();
307
+ $facetCounts = $result["facet_counts"];
308
+ if (!$facetCounts)
309
+ return $filters;
310
+
311
+ $facetFieldsPrefix = $this->getFacetFieldsPrefix();
312
+
313
+ // First, work with faceted fields
314
+ foreach ($facetCounts["facet_fields"] as $facetName => $values) {
315
+ $facetName = str_replace($facetFieldsPrefix, '', $facetName);
316
+
317
+ $attribute = Mage::getSingleton('eav/config')->getAttribute(Mage_Catalog_Model_Product::ENTITY, $facetName);
318
+ $facetLabel = $attribute->getFrontendLabel();
319
+ $optionsDictionary = array();
320
+ if ($attribute->usesSource()) {
321
+ $attrOptions = $attribute->getSource()->getAllOptions(false);
322
+ foreach ($attrOptions as $opt) {
323
+ $optionsDictionary[$opt["value"]] = $opt["label"];
324
+ }
325
+ }
326
+
327
+ $options = array();
328
+ $i = 0;
329
+ while ($i < count($values)) {
330
+ $optionName = $values[$i];
331
+ $optionLabel = isset($optionsDictionary[$optionName]) ? $optionsDictionary[$optionName] : $optionName;
332
+ if ($optionLabel) {
333
+ $count = $values[$i + 1];
334
+ if ($count > 0) {
335
+ $options[] = $this->createFilterOption($optionLabel, $optionName, $count);
336
+ }
337
+ }
338
+ $i+=2;
339
+ }
340
+ if (count($options) > 0) { // Only add filters with 1 or more options
341
+ $filters[] = $this->createFilterInfo($facetName, $facetLabel, $options);
342
+ }
343
+ }
344
+
345
+ // Second, go for price ranges if present
346
+ $ranges = $facetCounts["facet_ranges"];
347
+ if (!$ranges)
348
+ return $filters;
349
+ $priceField = $this->getEngineParam("price_field");
350
+ $priceRanges = $ranges[$priceField];
351
+ if (!$priceRanges)
352
+ return $filters;
353
+
354
+ $ranges = $priceRanges["counts"];
355
+ if (!$ranges)
356
+ return $filters;
357
+
358
+ $rangeConfig = $this->getPriceRangeConfiguration();
359
+ if (!$rangeConfig)
360
+ return $filters;
361
+
362
+ $gap = $rangeConfig["gap"];
363
+
364
+ $options = array();
365
+ $i = 0;
366
+ $valueCount = count($ranges);
367
+ while ($i < $valueCount) {
368
+ $priceStart = round($ranges[$i]);
369
+ $count = $ranges[$i + 1];
370
+ if ($count > 0) {
371
+ $options[] = $this->createFilterOption($priceStart . " - " . ($priceStart + $gap), $priceStart, $count);
372
+ }
373
+ $i+=2;
374
+ }
375
+ if (count($options) > 0) {
376
+ $desc = $this->__('Price');
377
+ $filters[] = $this->createFilterInfo(self::PRICE_PARAM_NAME, $desc, $options);
378
+ }
379
+ return $filters;
380
+ }
381
+
382
+ // Determines what available filters have been applied in the current request
383
+ private function getResponseAppliedFilter($availableFilters) {
384
+ $filters = array();
385
+ $request = $this->getRequest();
386
+ $config = $this->getPriceRangeConfiguration();
387
+ $gap = $config["gap"];
388
+
389
+ foreach ($availableFilters as $availableFilter) {
390
+
391
+ $parameterName = $availableFilter["param"];
392
+ $parameterValue = $request->getParam($parameterName);
393
+
394
+ if (!is_null($parameterValue) && trim($parameterValue)!="") {
395
+
396
+ if ($parameterName == self::PRICE_PARAM_NAME) {
397
+ $filters[] = $this->createAppliedFilter(
398
+ self::PRICE_PARAM_NAME, $this->__('Price'), $parameterValue, $parameterValue . " - " . ($parameterValue + $gap)
399
+ );
400
+ } else {
401
+ $product = Mage::getModel('catalog/product')->setData($parameterName, $parameterValue);
402
+ $valueLabel = $product->getAttributeText($parameterName);
403
+ $filters[] = $this->createAppliedFilter(
404
+ $availableFilter["param"], $availableFilter["paramLabel"], $parameterValue, $valueLabel
405
+ );
406
+ }
407
+ }
408
+ }
409
+ return $filters;
410
+ }
411
+
412
+ // Splits the search terms and generates an "OR" search expression
413
+ // Example: "hello world" -> "text:hello OR text:world"
414
+ private function generateQueryExpression($queryField, $searchTerm) {
415
+ $words = explode(" ", $searchTerm);
416
+ $result = "";
417
+ foreach ($words as $word) {
418
+ $word = trim($word);
419
+ if ($word) {
420
+ if ($result != "") {
421
+ $result .=" OR ";
422
+ }
423
+ $result .= $queryField . ":" . $word;
424
+ }
425
+ }
426
+ return $result;
427
+ }
428
+
429
+ private function checkEngineParams() {
430
+ $valid = $this->check("host");
431
+ $valid = $valid && $this->check("id_field");
432
+ $valid = $valid && $this->check("query_field");
433
+ $valid = $valid && $this->check("name_field");
434
+ $valid = $valid && $this->check("price_field");
435
+ $valid = $valid && $this->check("categories_field");
436
+ return $valid;
437
+ }
438
+
439
+ private function check($paramName) {
440
+ if (!$this->getEngineParam($paramName)) {
441
+ $this->log("Error: param $paramName is not defined");
442
+ return FALSE;
443
+ }
444
+ return TRUE;
445
+ }
446
+
447
+ private function getFacetFieldsPrefix() {
448
+ $facetFieldsPrefix = $this->getEngineParam("facet_fields_prefix");
449
+ return $facetFieldsPrefix ? $facetFieldsPrefix : "attr_nav_select_";
450
+ }
451
+
452
+ private function getPriceRangeConfiguration() {
453
+ $ranges = $this->getEngineParam("price_range");
454
+ $rangeValues = explode(",", $ranges);
455
+ $start = ($rangeValues && count($rangeValues) > 0) ? $rangeValues[0] : 0;
456
+ $end = ($rangeValues && count($rangeValues)) > 1 ? $rangeValues[1] : 9999999;
457
+ $gap = ($rangeValues && count($rangeValues)) > 2 ? $rangeValues[2] : 100;
458
+ $result = array(
459
+ "start" => $start,
460
+ "end" => $end,
461
+ "gap" => $gap
462
+ );
463
+ return $result;
464
+ }
465
+
466
+ }
app/code/community/LetsSyncroLLC/Oct8ne/Helper/Version.php CHANGED
@@ -8,6 +8,6 @@ class LetsSyncroLLC_Oct8ne_Helper_Version extends Mage_Core_Helper_Abstract {
8
  }
9
 
10
  static public function getApiVersion() {
11
- return "2.1";
12
  }
13
  }
8
  }
9
 
10
  static public function getApiVersion() {
11
+ return "2.2";
12
  }
13
  }
app/code/community/LetsSyncroLLC/Oct8ne/Model/ImageWidth.php ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class LetsSyncroLLC_Oct8ne_Model_ImageWidth extends Mage_Core_Model_Config_Data
4
+ {
5
+ public function save()
6
+ {
7
+ $n = $this->getValue();
8
+ if($n === "") {
9
+ return parent::save();
10
+ }
11
+
12
+ $i = intval($n);
13
+
14
+ if(!$i || $i<=0 ) {
15
+ MAge::throwException("Invalid image width.");
16
+ }
17
+
18
+ return parent::save(); //call original save method so whatever happened
19
+ //before still happens (the value saves)
20
+ }
21
+ }
22
+
app/code/community/LetsSyncroLLC/Oct8ne/Model/SearchEngines.php CHANGED
@@ -5,7 +5,9 @@ class LetsSyncroLLC_Oct8ne_Model_SearchEngines extends Mage_Core_Model_Abstract
5
  public function toOptionArray() {
6
  return array(
7
  array('value' => 'magento', 'label' => '(Default)'),
8
- array('value' => 'sli', 'label' => 'SLI Search')
 
 
9
  );
10
  }
11
 
5
  public function toOptionArray() {
6
  return array(
7
  array('value' => 'magento', 'label' => '(Default)'),
8
+ array('value' => 'sli', 'label' => 'SLI Search'),
9
+ array('value' => 'solr', 'label' => 'Solr'),
10
+ array('value' => 'celebros', 'label' => 'Celebros'),
11
  );
12
  }
13
 
app/code/community/LetsSyncroLLC/Oct8ne/controllers/FrameController.php CHANGED
@@ -7,6 +7,7 @@
7
  class LetsSyncroLLC_Oct8ne_FrameController extends Mage_Core_Controller_Front_Action {
8
 
9
  public function customerDataAction() {
 
10
  $customerDataHelper = Mage::helper('oct8ne/customerData');
11
  $login_data = $customerDataHelper->getLoginData();
12
  $wishlist_data = $customerDataHelper->getWishlistData();
@@ -23,40 +24,8 @@ class LetsSyncroLLC_Oct8ne_FrameController extends Mage_Core_Controller_Front_Ac
23
  $this->returnJson($results);
24
  }
25
 
26
- // REVIEW: Remove this function?
27
- public function productviewAction() {
28
- Mage::register('oct8ne_rewrite', 1, true); // lo usamos para deshabilitar el redirect
29
-
30
- $categoryId = (int) $this->getRequest()->getParam('category', false);
31
- $productId = (int) $this->getRequest()->getParam('id');
32
- $specifyOptions = $this->getRequest()->getParam('options');
33
-
34
- // Prepare helper and params
35
- $viewHelper = Mage::helper('catalog/product_view');
36
-
37
- $params = new Varien_Object();
38
- $params->setCategoryId($categoryId);
39
- $params->setSpecifyOptions($specifyOptions);
40
-
41
- // Render page
42
- try {
43
- $viewHelper->prepareAndRender($productId, $this, $params);
44
- } catch (Exception $e) {
45
- if ($e->getCode() == $viewHelper->ERR_NO_PRODUCT_LOADED) {
46
- if (isset($_GET['store']) && !$this->getResponse()->isRedirect()) {
47
- $this->_redirect('');
48
- } elseif (!$this->getResponse()->isRedirect()) {
49
- $this->_forward('noRoute');
50
- }
51
- } else {
52
- Mage::logException($e);
53
- $this->_forward('noRoute');
54
- }
55
- }
56
- }
57
-
58
  public function getAdapterInfoAction() {
59
-
60
  $model = Mage::getModel('oct8ne/letssyncro')->load(1);
61
  $enabled = $model ? $model->getEnabled() : FALSE;
62
 
@@ -78,6 +47,7 @@ class LetsSyncroLLC_Oct8ne_FrameController extends Mage_Core_Controller_Front_Ac
78
  }
79
 
80
  public function searchAction() {
 
81
 
82
  $profiler = Mage::helper('oct8ne/debug'); /* @var $profiler LetsSyncroLLC_Oct8ne_Helper_Debug */
83
  $actionStart = $profiler->startProfile("[FrameController] Starting search action");
@@ -88,6 +58,9 @@ class LetsSyncroLLC_Oct8ne_FrameController extends Mage_Core_Controller_Front_Ac
88
  $searchOrder = $this->getRequest()->getParam('orderby', 'relevance');
89
  $searchDir = $this->getRequest()->getParam('dir', 'asc');
90
  $page = $this->getRequest()->getParam("page", 1);
 
 
 
91
  $pageSize = $this->getRequest()->getParam('pageSize', 10);
92
 
93
  if (is_null($storeId)) {
@@ -154,6 +127,7 @@ class LetsSyncroLLC_Oct8ne_FrameController extends Mage_Core_Controller_Front_Ac
154
  }
155
 
156
  public function getCartAction() {
 
157
  $customerDataHelper = Mage::helper('oct8ne/customerData');
158
  $cart = $customerDataHelper->getCartData();
159
  $results = array(
@@ -164,6 +138,7 @@ class LetsSyncroLLC_Oct8ne_FrameController extends Mage_Core_Controller_Front_Ac
164
  }
165
 
166
  public function addToWishlistAction() {
 
167
  $productIds = $this->getRequest()->getParam('productIds', null);
168
  $result = false;
169
  if ($productIds) {
@@ -177,6 +152,7 @@ class LetsSyncroLLC_Oct8ne_FrameController extends Mage_Core_Controller_Front_Ac
177
  }
178
 
179
  public function removeFromWishlistAction() {
 
180
  $helper = Mage::helper('oct8ne/wishlist');
181
  $productId = $this->getRequest()->getParam('productId', null);
182
  $results = array(
@@ -186,6 +162,7 @@ class LetsSyncroLLC_Oct8ne_FrameController extends Mage_Core_Controller_Front_Ac
186
  }
187
 
188
  public function getWishlistAction() {
 
189
  $result_collection = Mage::helper('oct8ne/wishlist')->getWishlist();
190
  $results = array(
191
  'total' => count($result_collection),
@@ -195,6 +172,7 @@ class LetsSyncroLLC_Oct8ne_FrameController extends Mage_Core_Controller_Front_Ac
195
  }
196
 
197
  public function productInfoAction() {
 
198
  $profiler = Mage::helper('oct8ne/debug'); /* @var $profiler LetsSyncroLLC_Oct8ne_Helper_Debug */
199
  $actionStart = $profiler->startProfile("[FrameController] Starting ProductInfoAction");
200
 
@@ -211,6 +189,7 @@ class LetsSyncroLLC_Oct8ne_FrameController extends Mage_Core_Controller_Front_Ac
211
  }
212
 
213
  public function productSummaryAction() {
 
214
  $profiler = Mage::helper('oct8ne/debug'); /* @var $profiler LetsSyncroLLC_Oct8ne_Helper_Debug */
215
  $actionStart = $profiler->startProfile("[FrameController] Starting ProductSummaryAction");
216
  $products = $this->getRequest()->getParam('productIds', null);
@@ -226,6 +205,7 @@ class LetsSyncroLLC_Oct8ne_FrameController extends Mage_Core_Controller_Front_Ac
226
  }
227
 
228
  public function productRelatedAction() {
 
229
  $product_id = $this->getRequest()->getParam('productId', null);
230
  $page = $this->getRequest()->getParam('page', 1);
231
  $pageSize = $this->getRequest()->getParam('pageSize', 10);
@@ -234,6 +214,7 @@ class LetsSyncroLLC_Oct8ne_FrameController extends Mage_Core_Controller_Front_Ac
234
  }
235
 
236
  public function imageAction() {
 
237
  $file = $this->getRequest()->getParam('file', null);
238
  if ($file == null) {
239
  $this->returnNoContent();
@@ -254,6 +235,7 @@ class LetsSyncroLLC_Oct8ne_FrameController extends Mage_Core_Controller_Front_Ac
254
  }
255
 
256
  public function getSalesReportAction() {
 
257
  if (!$this->checkApiToken()) {
258
  $this->returnNotAuthorized();
259
  return false;
@@ -270,6 +252,7 @@ class LetsSyncroLLC_Oct8ne_FrameController extends Mage_Core_Controller_Front_Ac
270
 
271
  // Deprecated in API 2.1
272
  public function getReportDataAction() {
 
273
  if (!$this->checkApiToken()) {
274
  $this->returnNotAuthorized();
275
  return false;
@@ -325,6 +308,7 @@ class LetsSyncroLLC_Oct8ne_FrameController extends Mage_Core_Controller_Front_Ac
325
  }
326
 
327
  public function systemCheckAction() {
 
328
  $text = array();
329
  $text[] = get_class(Mage::getModel('core/url'));
330
  $text[] = get_class(Mage::getModel('core/url_rewrite'));
@@ -417,4 +401,31 @@ class LetsSyncroLLC_Oct8ne_FrameController extends Mage_Core_Controller_Front_Ac
417
  return Mage::helper($helperName);
418
  }
419
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
420
  }
7
  class LetsSyncroLLC_Oct8ne_FrameController extends Mage_Core_Controller_Front_Action {
8
 
9
  public function customerDataAction() {
10
+ $this->setEnvironment();
11
  $customerDataHelper = Mage::helper('oct8ne/customerData');
12
  $login_data = $customerDataHelper->getLoginData();
13
  $wishlist_data = $customerDataHelper->getWishlistData();
24
  $this->returnJson($results);
25
  }
26
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
  public function getAdapterInfoAction() {
28
+ $this->setEnvironment();
29
  $model = Mage::getModel('oct8ne/letssyncro')->load(1);
30
  $enabled = $model ? $model->getEnabled() : FALSE;
31
 
47
  }
48
 
49
  public function searchAction() {
50
+ $this->setEnvironment();
51
 
52
  $profiler = Mage::helper('oct8ne/debug'); /* @var $profiler LetsSyncroLLC_Oct8ne_Helper_Debug */
53
  $actionStart = $profiler->startProfile("[FrameController] Starting search action");
58
  $searchOrder = $this->getRequest()->getParam('orderby', 'relevance');
59
  $searchDir = $this->getRequest()->getParam('dir', 'asc');
60
  $page = $this->getRequest()->getParam("page", 1);
61
+ if ($page < 1) {
62
+ $page = 1;
63
+ }
64
  $pageSize = $this->getRequest()->getParam('pageSize', 10);
65
 
66
  if (is_null($storeId)) {
127
  }
128
 
129
  public function getCartAction() {
130
+ $this->setEnvironment();
131
  $customerDataHelper = Mage::helper('oct8ne/customerData');
132
  $cart = $customerDataHelper->getCartData();
133
  $results = array(
138
  }
139
 
140
  public function addToWishlistAction() {
141
+ $this->setEnvironment();
142
  $productIds = $this->getRequest()->getParam('productIds', null);
143
  $result = false;
144
  if ($productIds) {
152
  }
153
 
154
  public function removeFromWishlistAction() {
155
+ $this->setEnvironment();
156
  $helper = Mage::helper('oct8ne/wishlist');
157
  $productId = $this->getRequest()->getParam('productId', null);
158
  $results = array(
162
  }
163
 
164
  public function getWishlistAction() {
165
+ $this->setEnvironment();
166
  $result_collection = Mage::helper('oct8ne/wishlist')->getWishlist();
167
  $results = array(
168
  'total' => count($result_collection),
172
  }
173
 
174
  public function productInfoAction() {
175
+ $this->setEnvironment();
176
  $profiler = Mage::helper('oct8ne/debug'); /* @var $profiler LetsSyncroLLC_Oct8ne_Helper_Debug */
177
  $actionStart = $profiler->startProfile("[FrameController] Starting ProductInfoAction");
178
 
189
  }
190
 
191
  public function productSummaryAction() {
192
+ $this->setEnvironment();
193
  $profiler = Mage::helper('oct8ne/debug'); /* @var $profiler LetsSyncroLLC_Oct8ne_Helper_Debug */
194
  $actionStart = $profiler->startProfile("[FrameController] Starting ProductSummaryAction");
195
  $products = $this->getRequest()->getParam('productIds', null);
205
  }
206
 
207
  public function productRelatedAction() {
208
+ $this->setEnvironment();
209
  $product_id = $this->getRequest()->getParam('productId', null);
210
  $page = $this->getRequest()->getParam('page', 1);
211
  $pageSize = $this->getRequest()->getParam('pageSize', 10);
214
  }
215
 
216
  public function imageAction() {
217
+ $this->setEnvironment();
218
  $file = $this->getRequest()->getParam('file', null);
219
  if ($file == null) {
220
  $this->returnNoContent();
235
  }
236
 
237
  public function getSalesReportAction() {
238
+ $this->setEnvironment();
239
  if (!$this->checkApiToken()) {
240
  $this->returnNotAuthorized();
241
  return false;
252
 
253
  // Deprecated in API 2.1
254
  public function getReportDataAction() {
255
+ $this->setEnvironment();
256
  if (!$this->checkApiToken()) {
257
  $this->returnNotAuthorized();
258
  return false;
308
  }
309
 
310
  public function systemCheckAction() {
311
+ $this->setEnvironment();
312
  $text = array();
313
  $text[] = get_class(Mage::getModel('core/url'));
314
  $text[] = get_class(Mage::getModel('core/url_rewrite'));
401
  return Mage::helper($helperName);
402
  }
403
 
404
+ // Sets the current request environment (currency & locale)
405
+ private function setEnvironment() {
406
+
407
+ $app = Mage::app();
408
+ $request = $this->getRequest();
409
+
410
+ // Set currency, if nedded
411
+ $currency = $request->getParam('currency', null);
412
+ if ($currency) {
413
+ $store = $app->getStore();
414
+ $currentCurrency = $store->getCurrentCurrencyCode();
415
+ if($currency != $currentCurrency) {
416
+ $store->setCurrentCurrencyCode($currency);
417
+ }
418
+ }
419
+
420
+ // Set locale, if nedded
421
+ $locale = $request->getParam("locale", null);
422
+ if ($locale) {
423
+ $locale = str_replace("-", "_", $locale);
424
+ $currentLocale = $app->getLocale();
425
+ if ($locale != $currentLocale->getLocaleCode() && Zend_Locale::isLocale($locale)) {
426
+ $currentLocale->setLocale($locale);
427
+ }
428
+ }
429
+ }
430
+
431
  }
app/code/community/LetsSyncroLLC/Oct8ne/controllers/SetupController.php CHANGED
@@ -30,10 +30,13 @@ class LetsSyncroLLC_Oct8ne_SetupController extends Mage_Core_Controller_Front_Ac
30
  $settings = "";
31
  $dataList = array();
32
  $this->addSetting($dataList, $settings, 'oct8neSearch/assistedSearch/elementSelector', "Search element selector", 'CSS selector. Example: "#search"');
33
- $this->addSetting($dataList, $settings, 'oct8neSearch/searchEngine/engine', "Search engine", 'Allowed: { "magento", "sli" }');
34
  $this->addSetting($dataList, $settings, 'oct8neSearch/searchEngine/params', "Search engine settings", '"Search engine specific settings"');
35
  $this->addSetting($dataList, $settings, 'oct8neData/productData/productDataDescription', "Comma-separated product description fields", 'Example: "description, short_description"');
36
  $this->addSetting($dataList, $settings, 'oct8neData/productData/ignoreExcludedImages', "Ignore images marked as excluded", "1=true, 0=false");
 
 
 
37
  $this->addSetting($dataList, $settings, 'oct8neData/advancedDataConfig/imageHelperName', "Image helper name", 'Example: "default" to use helper/images/default.php');
38
  $this->addSetting($dataList, $settings, 'oct8neData/advancedDataConfig/loadCompleteProductInfo', "Load complete product info", "1=true, 0=false");
39
  $this->addSetting($dataList, $settings, 'oct8neData/advancedDataConfig/imageGalleryPrefetch', "Prefetch image gallery", "1=true, 0=false");
@@ -55,13 +58,21 @@ class LetsSyncroLLC_Oct8ne_SetupController extends Mage_Core_Controller_Front_Ac
55
  print_r($settings);
56
  print "</table>";
57
  print "<hr><form method='post' action='/oct8ne/setup/setsettings'>"
58
- . "Key: <input type='text' name='setting' list='settings' size='50'> "
59
- . "New value: <input type='text' name='value'> "
60
  . "<input type='hidden' name='apitoken' value='" . $this->getRequest()->getParam('apitoken', null) . "'>"
61
  . "<input type='submit'>"
62
  . "</form>"
63
  . "<p><a href='/oct8ne/setup'>Back to menu</a></p>"
64
- . "</body></html>";
 
 
 
 
 
 
 
 
65
  }
66
 
67
  public function setSettingsAction() {
@@ -118,7 +129,8 @@ class LetsSyncroLLC_Oct8ne_SetupController extends Mage_Core_Controller_Front_Ac
118
  . "<input type='submit'>"
119
  . "</form>"
120
  . "<p><a href='/oct8ne/setup'>Back to menu</a></p>"
121
- . "</body></html>";
 
122
  }
123
 
124
  public function setLinkupAction() {
@@ -146,16 +158,45 @@ class LetsSyncroLLC_Oct8ne_SetupController extends Mage_Core_Controller_Front_Ac
146
  private function addSetting(&$dataList, &$str, $setting, $title, $example = NULL) {
147
  $dataList[] = $setting;
148
  $result = Mage::getStoreConfig($setting);
 
149
  if (is_null($result) || $result == "") {
150
  $result = "(not set)";
151
  }
152
- $str .= "<tr><td>{$setting}</td><td>{$result}</td><td>{$title}</td><td>$example</td>";
153
  return $str;
154
  }
155
 
156
  private function isValidIp() {
157
- $ip = $_SERVER['REMOTE_ADDR'];
158
- return $ip == '127.0.0.1' || $ip == '80.28.120.5';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
159
  }
160
 
161
  private function returnBadRequest() {
30
  $settings = "";
31
  $dataList = array();
32
  $this->addSetting($dataList, $settings, 'oct8neSearch/assistedSearch/elementSelector', "Search element selector", 'CSS selector. Example: "#search"');
33
+ $this->addSetting($dataList, $settings, 'oct8neSearch/searchEngine/engine', "Search engine", 'Allowed: { "magento", "sli", "solr", "celebros" }');
34
  $this->addSetting($dataList, $settings, 'oct8neSearch/searchEngine/params', "Search engine settings", '"Search engine specific settings"');
35
  $this->addSetting($dataList, $settings, 'oct8neData/productData/productDataDescription', "Comma-separated product description fields", 'Example: "description, short_description"');
36
  $this->addSetting($dataList, $settings, 'oct8neData/productData/ignoreExcludedImages', "Ignore images marked as excluded", "1=true, 0=false");
37
+ $this->addSetting($dataList, $settings, 'oct8neData/productData/returnActualProductImageUrl', "Use product's actual images instead of 'image' action", "1=true, 0=false");
38
+ $this->addSetting($dataList, $settings, 'oct8neData/productData/actualProductImageWidth', "Product's actual images default width", "Example: '600' or empty for not resizing");
39
+ $this->addSetting($dataList, $settings, 'oct8neData/productData/ignoreBackorders', "Oct8ne should ignore the backorders property to determine stock availability", "1=true, 0=false");
40
  $this->addSetting($dataList, $settings, 'oct8neData/advancedDataConfig/imageHelperName', "Image helper name", 'Example: "default" to use helper/images/default.php');
41
  $this->addSetting($dataList, $settings, 'oct8neData/advancedDataConfig/loadCompleteProductInfo', "Load complete product info", "1=true, 0=false");
42
  $this->addSetting($dataList, $settings, 'oct8neData/advancedDataConfig/imageGalleryPrefetch', "Prefetch image gallery", "1=true, 0=false");
58
  print_r($settings);
59
  print "</table>";
60
  print "<hr><form method='post' action='/oct8ne/setup/setsettings'>"
61
+ . "Key: <input type='text' name='setting' id='setting' list='settings' size='50'> "
62
+ . "New value: <textarea name='value' id='value' style='vertical-align: top; margin-right: 10px'></textarea>"
63
  . "<input type='hidden' name='apitoken' value='" . $this->getRequest()->getParam('apitoken', null) . "'>"
64
  . "<input type='submit'>"
65
  . "</form>"
66
  . "<p><a href='/oct8ne/setup'>Back to menu</a></p>"
67
+ . "<script>"
68
+ . "function selectSetting(setting, value) {"
69
+ . " document.getElementById('setting').value = setting;"
70
+ . " document.getElementById('value').value = value;"
71
+ . " location.href='#setting';"
72
+ . "}"
73
+ . "</script>"
74
+ . "</body>"
75
+ . "</html>";
76
  }
77
 
78
  public function setSettingsAction() {
129
  . "<input type='submit'>"
130
  . "</form>"
131
  . "<p><a href='/oct8ne/setup'>Back to menu</a></p>"
132
+ . "</body>"
133
+ . "</html>";
134
  }
135
 
136
  public function setLinkupAction() {
158
  private function addSetting(&$dataList, &$str, $setting, $title, $example = NULL) {
159
  $dataList[] = $setting;
160
  $result = Mage::getStoreConfig($setting);
161
+ $actualResult = $result;
162
  if (is_null($result) || $result == "") {
163
  $result = "(not set)";
164
  }
165
+ $str .= "<tr><td style='cursor: pointer;' onclick=\"selectSetting('{$setting}', '{$actualResult}')\">{$setting}</td><td>{$result}</td><td>{$title}</td><td>$example</td>";
166
  return $str;
167
  }
168
 
169
  private function isValidIp() {
170
+ if($this->CheckIpFromHeader('REMOTE_ADDR')) {
171
+ return true;
172
+ }
173
+ if($this->CheckIpFromHeader('HTTP_X_FORWARDED_FOR')) {
174
+ return true;
175
+ }
176
+ if($this->CheckIpFromHeader('HTTP_CLIENT_IP')) {
177
+ return true;
178
+ }
179
+ if($this->CheckIpFromHeader('HTTP_X_FORWARDED')) {
180
+ return true;
181
+ }
182
+ if($this->CheckIpFromHeader('HTTP_X_CLUSTER_CLIENT_IP')) {
183
+ return true;
184
+ }
185
+ if($this->CheckIpFromHeader('HTTP_FORWARDED_FOR')) {
186
+ return true;
187
+ }
188
+ if($this->CheckIpFromHeader('HTTP_FORWARDED')) {
189
+ return true;
190
+ }
191
+ return false;
192
+ }
193
+
194
+ private function CheckIpFromHeader($header) {
195
+ if(!isset($_SERVER[$header]))
196
+ return FALSE;
197
+
198
+ $ip = $_SERVER[$header];
199
+ return $ip == '127.0.0.1' || $ip == '80.28.120.5' || $ip == '83.32.31.92' || $ip == '::1';
200
  }
201
 
202
  private function returnBadRequest() {
app/code/community/LetsSyncroLLC/Oct8ne/etc/config.xml CHANGED
@@ -2,7 +2,7 @@
2
  <config>
3
  <modules>
4
  <LetsSyncroLLC_Oct8ne>
5
- <version>2.1.1</version>
6
  </LetsSyncroLLC_Oct8ne>
7
  </modules>
8
 
@@ -24,8 +24,7 @@
24
  </order>
25
  </entities>
26
  </oct8ne_mysql4>
27
-
28
-
29
  <core>
30
  <rewrite>
31
  <url>LetsSyncroLLC_Oct8ne_Model_Mage_Url</url>
@@ -262,6 +261,8 @@
262
  <oct8neData>
263
  <productData>
264
  <ignoreExcludedImages>0</ignoreExcludedImages>
 
 
265
  </productData>
266
  <advancedDataConfig>
267
  <imageGalleryPrefetch>1</imageGalleryPrefetch>
2
  <config>
3
  <modules>
4
  <LetsSyncroLLC_Oct8ne>
5
+ <version>2.1.2</version>
6
  </LetsSyncroLLC_Oct8ne>
7
  </modules>
8
 
24
  </order>
25
  </entities>
26
  </oct8ne_mysql4>
27
+
 
28
  <core>
29
  <rewrite>
30
  <url>LetsSyncroLLC_Oct8ne_Model_Mage_Url</url>
261
  <oct8neData>
262
  <productData>
263
  <ignoreExcludedImages>0</ignoreExcludedImages>
264
+ <returnActualProductImageUrl>0</returnActualProductImageUrl>
265
+ <actualProductImageWidth>800</actualProductImageWidth>
266
  </productData>
267
  <advancedDataConfig>
268
  <imageGalleryPrefetch>1</imageGalleryPrefetch>
app/code/community/LetsSyncroLLC/Oct8ne/etc/system.xml CHANGED
@@ -10,6 +10,7 @@
10
  <sections>
11
  <oct8neData>
12
  <label>Data</label>
 
13
  <tab>oct8ne_tab</tab>
14
  <show_in_default>1</show_in_default>
15
  <show_in_website>1</show_in_website>
@@ -42,6 +43,36 @@
42
  <show_in_website>1</show_in_website>
43
  <show_in_store>1</show_in_store>
44
  </ignoreExcludedImages>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
  </fields>
46
  </productData>
47
  <advancedDataConfig translate="label">
@@ -73,7 +104,7 @@
73
  </loadCompleteProductInfo>
74
  <imageGalleryPrefetch translate="label">
75
  <label>Image Gallery Prefetch</label>
76
- <comment>Oct8ne should try to prefetch the image gallery to speed up product loading. Only applies if you selected "No" in ProductInfo Full Load.</comment>
77
  <source_model>Mage_Adminhtml_Model_System_Config_Source_Yesno</source_model>
78
  <frontend_type>select</frontend_type>
79
  <sort_order>30</sort_order>
@@ -89,6 +120,7 @@
89
  <oct8neSearch>
90
  <label>Search</label>
91
  <tab>oct8ne_tab</tab>
 
92
  <show_in_default>1</show_in_default>
93
  <show_in_website>1</show_in_website>
94
  <show_in_store>1</show_in_store>
@@ -137,7 +169,7 @@
137
  <params translate="label">
138
  <label>Search Engine Parameters</label>
139
  <comment>Enter the search engine configuration parameters. Example: "setting1=value1;setting2=value2"</comment>
140
- <frontend_type>text</frontend_type>
141
  <sort_order>20</sort_order>
142
  <show_in_default>1</show_in_default>
143
  <show_in_website>1</show_in_website>
10
  <sections>
11
  <oct8neData>
12
  <label>Data</label>
13
+ <sort_order>200</sort_order>
14
  <tab>oct8ne_tab</tab>
15
  <show_in_default>1</show_in_default>
16
  <show_in_website>1</show_in_website>
43
  <show_in_website>1</show_in_website>
44
  <show_in_store>1</show_in_store>
45
  </ignoreExcludedImages>
46
+ <ignoreBackorders>
47
+ <label>Ignore Backorders</label>
48
+ <comment>Oct8ne should ignore the backorders property to determine stock availability.</comment>
49
+ <source_model>Mage_Adminhtml_Model_System_Config_Source_Yesno</source_model>
50
+ <frontend_type>select</frontend_type>
51
+ <sort_order>20</sort_order>
52
+ <show_in_default>1</show_in_default>
53
+ <show_in_website>1</show_in_website>
54
+ <show_in_store>1</show_in_store>
55
+ </ignoreBackorders>
56
+ <returnActualProductImageUrl translate="label">
57
+ <label>Use product's actual images</label>
58
+ <comment>Oct8ne will return product's actual images instead of resizing them through the 'image' action.</comment>
59
+ <source_model>Mage_Adminhtml_Model_System_Config_Source_Yesno</source_model>
60
+ <frontend_type>select</frontend_type>
61
+ <sort_order>30</sort_order>
62
+ <show_in_default>1</show_in_default>
63
+ <show_in_website>1</show_in_website>
64
+ <show_in_store>1</show_in_store>
65
+ </returnActualProductImageUrl>
66
+ <actualProductImageWidth translate="label">
67
+ <label>Product's actual images default width</label>
68
+ <comment>Oct8ne will resize product's actual images to the specified width. Leave empty if the images must not be resized. &lt;strong&gt;This value is only applied when oct8ne is using the actual product's images&lt;/strong&gt;.</comment>
69
+ <backend_model>LetsSyncroLLC_Oct8ne_Model_ImageWidth</backend_model>
70
+ <frontend_type>text</frontend_type>
71
+ <sort_order>40</sort_order>
72
+ <show_in_default>1</show_in_default>
73
+ <show_in_website>1</show_in_website>
74
+ <show_in_store>1</show_in_store>
75
+ </actualProductImageWidth>
76
  </fields>
77
  </productData>
78
  <advancedDataConfig translate="label">
104
  </loadCompleteProductInfo>
105
  <imageGalleryPrefetch translate="label">
106
  <label>Image Gallery Prefetch</label>
107
+ <comment>Oct8ne should try to prefetch the image gallery to speed up product loading. &lt;strong&gt;Only applies if you selected "No" in ProductInfo Full Load&lt;/strong&gt;.</comment>
108
  <source_model>Mage_Adminhtml_Model_System_Config_Source_Yesno</source_model>
109
  <frontend_type>select</frontend_type>
110
  <sort_order>30</sort_order>
120
  <oct8neSearch>
121
  <label>Search</label>
122
  <tab>oct8ne_tab</tab>
123
+ <sort_order>210</sort_order>
124
  <show_in_default>1</show_in_default>
125
  <show_in_website>1</show_in_website>
126
  <show_in_store>1</show_in_store>
169
  <params translate="label">
170
  <label>Search Engine Parameters</label>
171
  <comment>Enter the search engine configuration parameters. Example: "setting1=value1;setting2=value2"</comment>
172
+ <frontend_type>textarea</frontend_type>
173
  <sort_order>20</sort_order>
174
  <show_in_default>1</show_in_default>
175
  <show_in_website>1</show_in_website>
app/code/community/LetsSyncroLLC/Oct8ne/sql/oct8ne_setup/mysql4-install-2.1.2.php ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ $installer = $this;
4
+ $installer->startSetup();
5
+
6
+
7
+ // *******************************************
8
+ // Create and populate table letssyncro
9
+ // *******************************************
10
+
11
+ $installer->run("
12
+ DROP TABLE IF EXISTS {$this->getTable('letssyncro')};
13
+ CREATE TABLE {$this->getTable('letssyncro')} (
14
+ `letssyncro_id` int(5) NOT NULL auto_increment,
15
+ `email` varchar(100) NULL,
16
+ `password` varchar(100) NULL,
17
+ `urlapi` varchar(100) NOT NULL,
18
+ `licenseid` varchar(32) NULL,
19
+ `apitoken` varchar(32) NULL,
20
+ `enabled` varchar(1) NULL,
21
+ PRIMARY KEY (`letssyncro_id`)
22
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
23
+ ");
24
+
25
+ try {
26
+
27
+ $linkupUrl = Mage::helper('oct8ne/url')->getOct8neLinkupServiceUrl();
28
+ $installer->run("
29
+ INSERT INTO {$this->getTable('letssyncro')}
30
+ (`letssyncro_id`, `email`, `password`, `urlapi`, `licenseid`, `apitoken`, `enabled`) VALUES
31
+ (1, '', '', '{$linkupUrl}', '', '', '0');
32
+ ");
33
+ } catch (\Exception $e) {
34
+ // the insert may fail if we run it more than once (duplicate key)
35
+ // we need this check to prevent errors during the rename of the module
36
+ }
37
+
38
+ // ***************
39
+ // Drop old tables
40
+ // ***************
41
+ $installer->run("
42
+ DROP TABLE IF EXISTS {$this->getTable('orderproducts')}
43
+ ");
44
+
45
+ $installer->run("
46
+ DROP TABLE IF EXISTS {$this->getTable('quoteproducts')}
47
+ ");
48
+
49
+ // *******************************************
50
+ // Create table for orders and quotes
51
+ // *******************************************
52
+
53
+ $ordersTable = $this->getTable('letssyncro_orders');
54
+ $installer->run("
55
+ CREATE TABLE IF NOT EXISTS {$ordersTable} (
56
+ `quote_id` int(11) unsigned NOT NULL,
57
+ `order_id` int(11) unsigned,
58
+ `store_id` int(11) unsigned NOT NULL,
59
+ `customer_id` int(11) unsigned,
60
+ `session_id` varchar(32) NOT NULL,
61
+ `price` decimal(12,2) NOT NULL,
62
+ `final_price` decimal (12,2) NOT NULL,
63
+ `currency` varchar(3) NOT NULL default 'USD',
64
+ `products_count` int(11) unsigned NOT NULL,
65
+ `items_count` int(11) unsigned NOT NULL,
66
+ `last_action` varchar(1) NOT NULL,
67
+ `utc_created` datetime NOT NULL default '0000-00-00 00:00:00',
68
+ `utc_last_modified` datetime NOT NULL default '0000-00-00 00:00:00',
69
+ PRIMARY KEY (`quote_id`),
70
+ INDEX `{$ordersTable}_modified`(`utc_last_modified`)
71
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8;"
72
+ );
73
+
74
+ $installer->endSetup();
app/code/community/LetsSyncroLLC/Oct8ne/sql/oct8ne_setup/mysql4-upgrade-2.1.0-2.1.1.php ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ $installer = $this;
4
+ $installer->startSetup();
5
+
6
+ // Nothing to do
7
+
8
+ $installer->endSetup();
app/code/community/LetsSyncroLLC/Oct8ne/sql/oct8ne_setup/mysql4-upgrade-2.1.1-2.1.2.php ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ $installer = $this;
4
+ $installer->startSetup();
5
+
6
+ // Nothing to do
7
+
8
+ $installer->endSetup();
app/design/frontend/base/default/template/oct8ne/letssyncro.phtml CHANGED
@@ -37,6 +37,7 @@ if (is_null(Mage::registry('oct8ne')) && !$disable) {
37
  }
38
 
39
  $locale = str_replace('_', '-', Mage::app()->getLocale()->getLocaleCode());
 
40
 
41
  $helper = Mage::helper('oct8ne/version');
42
  $apiVersion = $helper->getApiVersion();
@@ -44,7 +45,6 @@ if (is_null(Mage::registry('oct8ne')) && !$disable) {
44
  $adapterVersion = $helper->getAdapterVersion();
45
  $oct8neHostName = Mage::helper('oct8ne/url')->getOct8neHostName();
46
 
47
-
48
  echo <<<EOT
49
 
50
  <script type= "text/javascript">
@@ -62,7 +62,7 @@ if (is_null(Mage::registry('oct8ne')) && !$disable) {
62
  oct8ne.currentProduct = $currentProduct;
63
  oct8ne.addToCartHttpVerb = "post";
64
  oct8ne.locale = "$locale";
65
- oct8ne.currency = "$";
66
  EOT;
67
 
68
  if ($elementselector) {
37
  }
38
 
39
  $locale = str_replace('_', '-', Mage::app()->getLocale()->getLocaleCode());
40
+ $currencyCode = Mage::app()->getStore()->getCurrentCurrencyCode();
41
 
42
  $helper = Mage::helper('oct8ne/version');
43
  $apiVersion = $helper->getApiVersion();
45
  $adapterVersion = $helper->getAdapterVersion();
46
  $oct8neHostName = Mage::helper('oct8ne/url')->getOct8neHostName();
47
 
 
48
  echo <<<EOT
49
 
50
  <script type= "text/javascript">
62
  oct8ne.currentProduct = $currentProduct;
63
  oct8ne.addToCartHttpVerb = "post";
64
  oct8ne.locale = "$locale";
65
+ oct8ne.currencyCode = "$currencyCode";
66
  EOT;
67
 
68
  if ($elementselector) {
app/etc/modules/LetsSyncroLLC_Oct8ne.xml CHANGED
@@ -4,7 +4,7 @@
4
  <LetsSyncroLLC_Oct8ne>
5
  <active>true</active>
6
  <codePool>community</codePool>
7
- <version>2.1.1</version>
8
  <depends>
9
  <Mage_Eav/>
10
  <Mage_Dataflow/>
4
  <LetsSyncroLLC_Oct8ne>
5
  <active>true</active>
6
  <codePool>community</codePool>
7
+ <version>2.1.2</version>
8
  <depends>
9
  <Mage_Eav/>
10
  <Mage_Dataflow/>
package.xml CHANGED
@@ -1,19 +1,20 @@
1
  <?xml version="1.0"?>
2
  <package>
3
  <name>LetsSyncroLLC_Oct8ne</name>
4
- <version>2.1.1</version>
5
  <stability>stable</stability>
6
  <license uri="http://www.opensource.org/licenses/gpl-license.php">GPL</license>
7
  <channel>community</channel>
8
  <extends/>
9
  <summary>Oct8ne extension</summary>
10
  <description>Agent-assisted search, proprietary co-viewing technology, &amp; live chat to engage in personal selling &amp; service.</description>
11
- <notes>Minor bugs fixed&#xD;
12
- Different routes configuration(front-admin)</notes>
 
13
  <authors><author><name>Oct8ne</name><user>Oct8ne</user><email>xavier.gonzalez@oct8ne.com</email></author></authors>
14
- <date>2015-08-13</date>
15
- <time>15:00:14</time>
16
- <contents><target name="magecommunity"><dir name="LetsSyncroLLC"><dir name="Oct8ne"><dir name="Block"><file name="Accountconfig.php" hash="6a1e95bd440f283ae9f19a01bc678cd9"/><dir name="Customer"><file name="Notifier.php" hash="58785a446c6c6a69db0348b81852028b"/></dir><dir name="Html"><file name="Head.php" hash="7fec049acbd3391ce0176982eede105b"/></dir><file name="Index.php" hash="d4cc07e7e6412cb9f3cedf2508f56461"/><dir name="Mage"><dir name="Product"><file name="View.php" hash="ca15ba7c5cc756cc18af5c9c48fbe492"/></dir></dir></dir><dir name="Helper"><file name="CustomerData.php" hash="38658993e66fee8d5e3170658fa71556"/><file name="Data.php" hash="4e7af56ca41c49ba61227c38a895cdd2"/><file name="Debug.php" hash="147f2d06848b4596a0409b471cf0769a"/><dir name="Image"><file name="Default.php" hash="bdf72fef9e9715ab52dbc0fb3409e7dd"/><file name="Schuler.php" hash="f0b16d49d5e9c4bceaa6170448be9414"/></dir><file name="Reports.php" hash="6df3362a381e507a69fbf27162174f1b"/><dir name="Search"><file name="Base.php" hash="58ed2efec43d92934fb039187be35271"/><file name="Magento.php" hash="0ae593bd70db8952c897682082594c10"/><file name="Sli.php" hash="7bce03311e5612b29b45f18c9e1de1b9"/></dir><file name="Url.php" hash="c1ea68e020ccf7c3622028a3ca6fb4c7"/><file name="Version.php" hash="392d8d155afefc4ee944feb13ff65715"/><file name="Wishlist.php" hash="95a30da6de9131026580e6475a2ea951"/></dir><dir name="Model"><file name="Cron.php" hash="11fbdce80ef509a89cbc055960c627dd"/><file name="Letssyncro.php" hash="a7755ee759fa31f004207823314a907d"/><dir name="Mage"><file name="Onepage.php" hash="400ea1de621a7d2e6b0e04db55b60027"/><file name="Request.php" hash="feee181c817bc4a1ed8d662104ddb1af"/><file name="Rewrite.php" hash="5699a8b1707724c4ad01fd6998cf12d6"/><file name="Url.php" hash="82a05832eaea74fedfd2c5b081dc5cc6"/></dir><dir name="Mysql4"><dir name="LetsSyncro"><file name="Collection.php" hash="1820b31106065627aa81007f966de6b7"/></dir><file name="Letssyncro.php" hash="81b49a4f7770d408eacd230a41434cbf"/><dir name="Order"><file name="Collection.php" hash="431a18fb0f8a2d29ea44a1b617b48382"/></dir><file name="Order.php" hash="1fd857af382915617c1d64d438a842ab"/></dir><file name="Observer.php" hash="bdfb77a7082ac8c27756b5bf7f4779df"/><file name="Order.php" hash="5ea076e3f76f9a28a5ab6eee1f157b69"/><file name="Orderproducts.php" hash="9edf0ab5159b046d0d33c2766087183f"/><file name="Quoteproducts.php" hash="3b6baf23d5ab4136c52fe24d470a3fd0"/><file name="SearchEngines.php" hash="1c65dab5b3dadcb78f145d9deb981e8b"/></dir><dir name="controllers"><file name="AccountController.php" hash="c900a756947b61498e5edd2e39b1d0bf"/><file name="FrameController.php" hash="f68e735597645fcc66f8bd94a4ace43e"/><file name="IndexController.php" hash="5a63469c2dead9b78a262fd580a3e43b"/><file name="Oct8neAdminController.php" hash="159d851a7b51f3483ebdfe2b49b05b4a"/><file name="SetupController.php" hash="b91c72f12d124862349744861e5516d5"/></dir><dir name="etc"><file name="config.xml" hash="a5059c377f2fed418f268b6850dedf7d"/><file name="system.xml" hash="0dcbd9bb7e4d44a731eecd35d358ed06"/></dir><dir name="sql"><dir name="oct8ne_setup"><file name="mysql4-install-2.0.0.php" hash="7cd9ed6b373a104ec7a27b1b2f26b570"/><file name="mysql4-install-2.1.0.php" hash="0c268a08bbfc48a072fdfb75c7013a43"/><file name="mysql4-upgrade-1-2.1.0.php" hash="5883e47d9718350d49146e33ba8fbd84"/><file name="mysql4-upgrade-1.0.0-1.1.0.php" hash="0944f9c420562fa8071b04eff2abdb15"/><file name="mysql4-upgrade-1.1.6-1.1.7.php" hash="eecd1f66e51507306abf5e4fa5d70584"/><file name="mysql4-upgrade-1.1.7-2.0.0.php" hash="3c7e1655fb0b45dd5dc01aca98929679"/><file name="mysql4-upgrade-2.0.0-2.0.3.php" hash="0288d291dec83584d97052e62b64a738"/><file name="mysql4-upgrade-2.0.3-2.1.0.php" hash="4a06d9802360e45a08d417168c260f15"/></dir></dir></dir></dir></target><target name="magedesign"><dir name="frontend"><dir name="default"><dir name="oct8ne"><dir name="layout"><file name="oct8ne.xml" hash="664f6b6c51799aba0fa905cbc80eb703"/></dir><dir name="template"><dir name="page"><file name="1column.phtml" hash="3fbf17f71254a75cbf3261eab5a727ab"/><file name="2columns-left.phtml" hash="3fbf17f71254a75cbf3261eab5a727ab"/><file name="2columns-right.phtml" hash="3fbf17f71254a75cbf3261eab5a727ab"/><file name="3columns.phtml" hash="3fbf17f71254a75cbf3261eab5a727ab"/></dir></dir></dir></dir><dir name="base"><dir name="default"><dir name="layout"><file name="oct8ne.xml" hash="4b6f167fdbaf25f864934c0e8ecdda51"/></dir><dir name="template"><dir name="oct8ne"><dir name="frame"><file name="clean-page.phtml" hash="86c6580270709b8adb8a624130704cb5"/><dir name="productview"><file name="additional.phtml" hash="d0f80a4f31b31154af12197301cbc524"/><file name="addto.phtml" hash="358f19e35ff76f853cfad50ad35329fc"/><file name="addtocart.phtml" hash="06ac8be9a7197e87e8c5972c27804cc9"/><file name="attributes.phtml" hash="def5531385ad60aac88274bd91f76f52"/><file name="description.phtml" hash="09674e0a56d36f27c93d3a52c3a880c4"/><file name="media.phtml" hash="b23c4e9ef29e00d2f592d822fec8e52c"/><file name="media.phtml.ORIGINAL" hash="071f4d92269b2cbfa1a14271afbf0dbe"/><dir name="options"><file name="js.phtml" hash="7d9917d908ca99033c3473ecc10d895d"/><dir name="type"><file name="date.phtml" hash="41a612891cda695e3023d15a460c4325"/><file name="default.phtml" hash="b6f6d8e715f2a1d59913f313654fc38a"/><file name="file.phtml" hash="5e336ccdfa66b78264e5a0e859600d74"/><file name="select.phtml" hash="162f029fc825b78676cce70633805e62"/><file name="text.phtml" hash="c2c2940fb278d952e0e0d5d232ba5ed9"/></dir><dir name="wrapper"><file name="bottom.phtml" hash="182b49972e67cc834b8e1094a3984f5b"/></dir><file name="wrapper.phtml" hash="b635f6abf10b920afb6000b462134db6"/></dir><file name="options.phtml" hash="60d92d70da66f28300788027aa6f3056"/><file name="price.phtml" hash="06e90ec3368d07d62c3895f706069f96"/><file name="price_clone.phtml" hash="fb1ca9b19f97b0498f529b96c5c0e372"/><file name="tierprices.phtml" hash="4ac50d3c9f54d11fa5041a361485da74"/><dir name="type"><file name="configurable.phtml" hash="b9a427816f9c8a3d0d7179e8d5382683"/><file name="default.phtml" hash="e7f000d4b7fbc62f4e155e429f976126"/><file name="grouped.phtml" hash="9ce42ac44794853963bf68e9f2e911b0"/><dir name="options"><file name="configurable.phtml" hash="2636b369c1ceacd1b131f77ade2c996f"/></dir><file name="simple.phtml" hash="b9a427816f9c8a3d0d7179e8d5382683"/><file name="virtual.phtml" hash="b9a427816f9c8a3d0d7179e8d5382683"/></dir></dir><file name="productview.phtml" hash="da287c78285ecb003bbee37491d3a2f2"/></dir><file name="letssyncro.phtml" hash="eb7f45eaf7ec0f6518accc417ecf4df7"/></dir></dir></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="LetsSyncroLLC_Oct8ne.xml" hash="15b2830b86e6a59998b79f4c44da09e5"/></dir></target><target name="magelocale"><dir><dir name="en_US"><file name="LetsSyncroLLC_Oct8ne.csv" hash="686df4107da7e35e243b629c5ee57963"/></dir><dir name="es_ES"><file name="LetsSyncroLLC_Oct8ne.csv" hash="eb0b3ddaae1e2e52005e9ab23cb37163"/></dir></dir></target><target name="mageskin"><dir name="frontend"><dir name="base"><dir name="default"><file name="oct8ne.css" hash="4255fddac8c054bbe32621cdccf844b8"/></dir></dir></dir><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="images"><file name="LetsSyncro_Logo.png" hash="2104af20cc380d0c745531e1dca2f97c"/></dir></dir></dir></dir></target></contents>
17
  <compatible/>
18
  <dependencies><required><php><min>5.3.0</min><max>6.0.0</max></php></required></dependencies>
19
  </package>
1
  <?xml version="1.0"?>
2
  <package>
3
  <name>LetsSyncroLLC_Oct8ne</name>
4
+ <version>2.1.2</version>
5
  <stability>stable</stability>
6
  <license uri="http://www.opensource.org/licenses/gpl-license.php">GPL</license>
7
  <channel>community</channel>
8
  <extends/>
9
  <summary>Oct8ne extension</summary>
10
  <description>Agent-assisted search, proprietary co-viewing technology, &amp; live chat to engage in personal selling &amp; service.</description>
11
+ <notes>Currency and language support.&#xD;
12
+ Added 2 new search engines: Solr , Celebros&#xD;
13
+ Minor bugs fixed</notes>
14
  <authors><author><name>Oct8ne</name><user>Oct8ne</user><email>xavier.gonzalez@oct8ne.com</email></author></authors>
15
+ <date>2016-02-11</date>
16
+ <time>14:18:27</time>
17
+ <contents><target name="magecommunity"><dir name="LetsSyncroLLC"><dir name="Oct8ne"><dir name="Block"><file name="Accountconfig.php" hash="283347a4600609e266ef17c58c2bd274"/><dir name="Customer"><file name="Notifier.php" hash="58785a446c6c6a69db0348b81852028b"/></dir><dir name="Html"><file name="Head.php" hash="7fec049acbd3391ce0176982eede105b"/></dir><file name="Index.php" hash="d4cc07e7e6412cb9f3cedf2508f56461"/><dir name="Mage"><dir name="Product"><file name="View.php" hash="ca15ba7c5cc756cc18af5c9c48fbe492"/></dir></dir></dir><dir name="Helper"><file name="CustomerData.php" hash="38658993e66fee8d5e3170658fa71556"/><file name="Data.php" hash="82ea0f1c975e9a44bf287606eb529391"/><file name="Debug.php" hash="147f2d06848b4596a0409b471cf0769a"/><dir name="Image"><file name="Default.php" hash="74ff374e88db99c4ae911bd3303e4c8e"/><file name="Schuler.php" hash="ea104cd9d9df2c62beab7af298e45fe1"/></dir><file name="Reports.php" hash="6df3362a381e507a69fbf27162174f1b"/><dir name="Search"><file name="Base.php" hash="7abe2fbdd34cead6bcfd3b72b739054c"/><file name="Celebros.php" hash="9c7007d3a3501d63af8207e107f6ac0f"/><dir name="CelebrosAPI"><file name="QwiserAnswer.php" hash="56f07a272ce8de8738868fc4c7a74165"/><file name="QwiserAnswers.php" hash="a7ac00848b3f60935771880b75aba90c"/><file name="QwiserConcept.php" hash="32ffebe11630864b666fe66f37eab1b2"/><file name="QwiserConcepts.php" hash="0b3c0fada961fe22dd6cbb3a4b719d2a"/><file name="QwiserProduct.php" hash="09069308e5f5fc862ddafebe7152f40b"/><file name="QwiserProductAnswer.php" hash="9dc1c8c9a929affa9db5a339ac1b7317"/><file name="QwiserProductAnswers.php" hash="699fc568eeb8bfc3d4bcc9b24102d3ad"/><file name="QwiserProductField.php" hash="273c36aad014b9220201881738eeafea"/><file name="QwiserProductFields.php" hash="4670e55b10d57c4208d9e5bacdd1d91c"/><file name="QwiserProducts.php" hash="cf2f76940b1c508823d00fbb7817cd06"/><file name="QwiserProductsMetaData.php" hash="4d54fae9b996ea18bbad5a60cd72c52a"/><file name="QwiserQuestion.php" hash="a148b2193de6967c3a12f43b939b92f2"/><file name="QwiserQuestions.php" hash="9de5d58ab267ea6a4ea9084d54920ddd"/><file name="QwiserSearchAPI.php" hash="e2680c99083553f6e0dc908ba3875603"/><file name="QwiserSearchPath.php" hash="300327589bf6720d0ae400c9cce755e7"/><file name="QwiserSearchPathEntry.php" hash="6e4192df47fc6c7ebdbb6251b6401e57"/><file name="QwiserSearchResults.php" hash="379337770db03fc27377be8de14ebd55"/><file name="QwiserSpellerInformation.php" hash="c52100535c3f0dc9650740cdbda6e40a"/><file name="SearchInformation.php" hash="de29fd1136f2512c18603164abfa58af"/><file name="SortingOptions.php" hash="a55d1eaabfee811b9f71dfdbb61f5c9a"/><file name="domxml-php4-to-php5.php" hash="29c0571bea402f63987c09d811d1a662"/></dir><file name="Magento.php" hash="0ae593bd70db8952c897682082594c10"/><file name="Sli.php" hash="c3cbe01a28f09a0e83bffb7764fb40c1"/><file name="Solr.php" hash="e391c51c27d6004e193281605603358d"/></dir><file name="Url.php" hash="c1ea68e020ccf7c3622028a3ca6fb4c7"/><file name="Version.php" hash="2e9384d1d71e8c52b0fd5f66bdbf843b"/><file name="Wishlist.php" hash="95a30da6de9131026580e6475a2ea951"/></dir><dir name="Model"><file name="Cron.php" hash="11fbdce80ef509a89cbc055960c627dd"/><file name="ImageWidth.php" hash="ddffd8d74a25f989b1116a663ac3a9e6"/><file name="Letssyncro.php" hash="a7755ee759fa31f004207823314a907d"/><dir name="Mage"><file name="Onepage.php" hash="400ea1de621a7d2e6b0e04db55b60027"/><file name="Request.php" hash="feee181c817bc4a1ed8d662104ddb1af"/><file name="Rewrite.php" hash="5699a8b1707724c4ad01fd6998cf12d6"/><file name="Url.php" hash="82a05832eaea74fedfd2c5b081dc5cc6"/></dir><dir name="Mysql4"><dir name="LetsSyncro"><file name="Collection.php" hash="1820b31106065627aa81007f966de6b7"/></dir><file name="Letssyncro.php" hash="81b49a4f7770d408eacd230a41434cbf"/><dir name="Order"><file name="Collection.php" hash="431a18fb0f8a2d29ea44a1b617b48382"/></dir><file name="Order.php" hash="1fd857af382915617c1d64d438a842ab"/></dir><file name="Observer.php" hash="bdfb77a7082ac8c27756b5bf7f4779df"/><file name="Order.php" hash="5ea076e3f76f9a28a5ab6eee1f157b69"/><file name="Orderproducts.php" hash="9edf0ab5159b046d0d33c2766087183f"/><file name="Quoteproducts.php" hash="3b6baf23d5ab4136c52fe24d470a3fd0"/><file name="SearchEngines.php" hash="d894f3f32f74bde7899db50dcf3e2719"/></dir><dir name="controllers"><file name="AccountController.php" hash="c900a756947b61498e5edd2e39b1d0bf"/><file name="FrameController.php" hash="7bf5aa77dc8db63ad87852f827fe31fe"/><file name="IndexController.php" hash="5a63469c2dead9b78a262fd580a3e43b"/><file name="Oct8neAdminController.php" hash="159d851a7b51f3483ebdfe2b49b05b4a"/><file name="SetupController.php" hash="106bfaad55a83d632cf176be3590badd"/></dir><dir name="etc"><file name="config.xml" hash="d992cb86aea439fc0919cebb19142201"/><file name="system.xml" hash="a993ef807a9c88f89354d66ef2dd4ae7"/></dir><dir name="sql"><dir name="oct8ne_setup"><file name="mysql4-install-2.0.0.php" hash="7cd9ed6b373a104ec7a27b1b2f26b570"/><file name="mysql4-install-2.1.0.php" hash="0c268a08bbfc48a072fdfb75c7013a43"/><file name="mysql4-install-2.1.2.php" hash="0c268a08bbfc48a072fdfb75c7013a43"/><file name="mysql4-upgrade-1-2.1.0.php" hash="5883e47d9718350d49146e33ba8fbd84"/><file name="mysql4-upgrade-1.0.0-1.1.0.php" hash="0944f9c420562fa8071b04eff2abdb15"/><file name="mysql4-upgrade-1.1.6-1.1.7.php" hash="eecd1f66e51507306abf5e4fa5d70584"/><file name="mysql4-upgrade-1.1.7-2.0.0.php" hash="3c7e1655fb0b45dd5dc01aca98929679"/><file name="mysql4-upgrade-2.0.0-2.0.3.php" hash="0288d291dec83584d97052e62b64a738"/><file name="mysql4-upgrade-2.0.3-2.1.0.php" hash="4a06d9802360e45a08d417168c260f15"/><file name="mysql4-upgrade-2.1.0-2.1.1.php" hash="0288d291dec83584d97052e62b64a738"/><file name="mysql4-upgrade-2.1.1-2.1.2.php" hash="0288d291dec83584d97052e62b64a738"/></dir></dir></dir></dir></target><target name="magedesign"><dir name="frontend"><dir name="default"><dir name="oct8ne"><dir name="layout"><file name="oct8ne.xml" hash="664f6b6c51799aba0fa905cbc80eb703"/></dir><dir name="template"><dir name="page"><file name="1column.phtml" hash="3fbf17f71254a75cbf3261eab5a727ab"/><file name="2columns-left.phtml" hash="3fbf17f71254a75cbf3261eab5a727ab"/><file name="2columns-right.phtml" hash="3fbf17f71254a75cbf3261eab5a727ab"/><file name="3columns.phtml" hash="3fbf17f71254a75cbf3261eab5a727ab"/></dir></dir></dir></dir><dir name="base"><dir name="default"><dir name="layout"><file name="oct8ne.xml" hash="4b6f167fdbaf25f864934c0e8ecdda51"/></dir><dir name="template"><dir name="oct8ne"><dir name="frame"><file name="clean-page.phtml" hash="86c6580270709b8adb8a624130704cb5"/><dir name="productview"><file name="additional.phtml" hash="d0f80a4f31b31154af12197301cbc524"/><file name="addto.phtml" hash="358f19e35ff76f853cfad50ad35329fc"/><file name="addtocart.phtml" hash="06ac8be9a7197e87e8c5972c27804cc9"/><file name="attributes.phtml" hash="def5531385ad60aac88274bd91f76f52"/><file name="description.phtml" hash="09674e0a56d36f27c93d3a52c3a880c4"/><file name="media.phtml" hash="b23c4e9ef29e00d2f592d822fec8e52c"/><file name="media.phtml.ORIGINAL" hash="071f4d92269b2cbfa1a14271afbf0dbe"/><dir name="options"><file name="js.phtml" hash="7d9917d908ca99033c3473ecc10d895d"/><dir name="type"><file name="date.phtml" hash="41a612891cda695e3023d15a460c4325"/><file name="default.phtml" hash="b6f6d8e715f2a1d59913f313654fc38a"/><file name="file.phtml" hash="5e336ccdfa66b78264e5a0e859600d74"/><file name="select.phtml" hash="162f029fc825b78676cce70633805e62"/><file name="text.phtml" hash="c2c2940fb278d952e0e0d5d232ba5ed9"/></dir><dir name="wrapper"><file name="bottom.phtml" hash="182b49972e67cc834b8e1094a3984f5b"/></dir><file name="wrapper.phtml" hash="b635f6abf10b920afb6000b462134db6"/></dir><file name="options.phtml" hash="60d92d70da66f28300788027aa6f3056"/><file name="price.phtml" hash="06e90ec3368d07d62c3895f706069f96"/><file name="price_clone.phtml" hash="fb1ca9b19f97b0498f529b96c5c0e372"/><file name="tierprices.phtml" hash="4ac50d3c9f54d11fa5041a361485da74"/><dir name="type"><file name="configurable.phtml" hash="b9a427816f9c8a3d0d7179e8d5382683"/><file name="default.phtml" hash="e7f000d4b7fbc62f4e155e429f976126"/><file name="grouped.phtml" hash="9ce42ac44794853963bf68e9f2e911b0"/><dir name="options"><file name="configurable.phtml" hash="2636b369c1ceacd1b131f77ade2c996f"/></dir><file name="simple.phtml" hash="b9a427816f9c8a3d0d7179e8d5382683"/><file name="virtual.phtml" hash="b9a427816f9c8a3d0d7179e8d5382683"/></dir></dir><file name="productview.phtml" hash="da287c78285ecb003bbee37491d3a2f2"/></dir><file name="letssyncro.phtml" hash="ab7c4d6a663cc9f7b5d69d981ade1688"/></dir></dir></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="LetsSyncroLLC_Oct8ne.xml" hash="ba2db49f4337a40d008efd8c8c70381c"/></dir></target><target name="magelocale"><dir><dir name="en_US"><file name="LetsSyncroLLC_Oct8ne.csv" hash="686df4107da7e35e243b629c5ee57963"/></dir><dir name="es_ES"><file name="LetsSyncroLLC_Oct8ne.csv" hash="eb0b3ddaae1e2e52005e9ab23cb37163"/></dir></dir></target><target name="mageskin"><dir name="frontend"><dir name="base"><dir name="default"><file name="oct8ne.css" hash="4255fddac8c054bbe32621cdccf844b8"/></dir></dir></dir><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="images"><file name="LetsSyncro_Logo.png" hash="2104af20cc380d0c745531e1dca2f97c"/></dir></dir></dir></dir></target></contents>
18
  <compatible/>
19
  <dependencies><required><php><min>5.3.0</min><max>6.0.0</max></php></required></dependencies>
20
  </package>