FINDOLOGIC_OnSiteSearch - Version 1.0.4

Version Notes

Findologic Search module

Download this release

Release Info

Developer FINDOLOGIC
Extension FINDOLOGIC_OnSiteSearch
Version 1.0.4
Comparing to
See all releases


Version 1.0.4

app/code/community/FINDOLOGIC/OnSiteSearch/Helper/TrackingScripts.php ADDED
@@ -0,0 +1,375 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The MIT License (MIT)
4
+ *
5
+ * Copyright (c) 2016 FINDOLOGIC
6
+ *
7
+ * Permission is hereby granted, free of charge, to any person obtaining a
8
+ * copy of this software and associated documentation files (the "Software"),
9
+ * to deal in the Software without restriction, including without limitation
10
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11
+ * and/or sell copies of the Software, and to permit persons to whom
12
+ * the Software is furnished to do so, subject to the following conditions:
13
+ *
14
+ * The above copyright notice and this permission notice shall be included
15
+ * in all copies or substantial portions of the Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
18
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
19
+ * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
22
+ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+ */
24
+ class FINDOLOGIC_OnSiteSearch_Helper_TrackingScripts extends Mage_Core_Helper_Abstract
25
+ {
26
+ /**
27
+ * @var array
28
+ */
29
+ private $data;
30
+
31
+ /**
32
+ * Used for caching categories retrieved from database.
33
+ * @var array
34
+ */
35
+ private static $categories = array();
36
+
37
+ /**
38
+ * Renders needed scripts for current page.
39
+ *
40
+ * @param Mage_Core_Controller_Request_Http $request
41
+ *
42
+ * @return string
43
+ */
44
+ public function renderScripts(Mage_Core_Controller_Request_Http $request)
45
+ {
46
+ $findologic = $request->get('findologic');
47
+ $result = '';
48
+
49
+ if ($findologic != 'off' && $this->getShopKey()) {
50
+ // Inserting js files for every page
51
+ $result .= $this->headJs();
52
+ $result .= $this->addHeadJs();
53
+
54
+ $module = $request->getModuleName();
55
+ $controller = $request->getControllerName();
56
+ $action = $request->getActionName();
57
+
58
+ if (Mage::registry('current_product')) {
59
+ $result .= $this->productJs($request);
60
+ } else if ($module == 'checkout' && $controller == 'onepage' && $action == 'success') {
61
+ $result .= $this->checkoutJs($request);
62
+ } else if ($module == 'checkout' && $controller == 'cart' && $action == 'index') {
63
+ $result .= $this->cartJs();
64
+ //} else if (Mage::registry('current_category')) {
65
+ // $result .= $this->categoryJs();
66
+ }
67
+ }
68
+
69
+ return $result;
70
+ }
71
+
72
+ /**
73
+ * Sets last order ID used in tracking of orders. Called for event observer. @see FINDOLOGIC_OnSiteSearch_Model_Observer
74
+ *
75
+ * @param int $orderId
76
+ */
77
+ public function setLastOrderId($orderId)
78
+ {
79
+ $this->data['LAST_ORDER_ID'] = $orderId;
80
+ }
81
+
82
+ /**
83
+ * Returns tracking js script for head (all pages).
84
+ *
85
+ * @return string
86
+ */
87
+ private function headJs()
88
+ {
89
+ $this->getConfData();
90
+
91
+ $headJs = sprintf(
92
+ '<script type="text/javascript">
93
+ (function() {
94
+ var flDataMain = "https://cdn.findologic.com/autocomplete/%s/autocomplete.js?usergrouphash=%s";
95
+ var flAutocomplete = document.createElement(\'script\');
96
+ flAutocomplete.type = \'text/javascript\';
97
+ flAutocomplete.async = true;
98
+ flAutocomplete.src = "https://cdn.findologic.com/autocomplete/require.js";
99
+ var s = document.getElementsByTagName(\'script\')[0];
100
+ flAutocomplete.setAttribute(\'data-main\', flDataMain);
101
+ s.parentNode.insertBefore(flAutocomplete, s);
102
+ })();
103
+ </script>', $this->data['PLACEHOLDER_1'], $this->data['PLACEHOLDER_2']);
104
+
105
+ return $headJs;
106
+ }
107
+
108
+ /**
109
+ * Returns additional tracking js script for head (all pages).
110
+ *
111
+ * @return string
112
+ */
113
+ private function addHeadJs()
114
+ {
115
+ $addHeadJs = sprintf(
116
+ '<script type="text/javascript">
117
+ var _paq = _paq || [];
118
+ (function(){ var u=(("https:" == document.location.protocol) ? "https://tracking.findologic.com/" : "http://tracking.findologic.com/");
119
+ _paq.push([\'setSiteId\', \'%s\']);
120
+ _paq.push([\'setTrackerUrl\', u+\'tracking.php\']);
121
+ _paq.push([\'trackPageView\']);
122
+ _paq.push([\'enableLinkTracking\']);
123
+ var d=document, g=d.createElement(\'script\'), s=d.getElementsByTagName(\'script\')[0]; g.type=\'text/javascript\'; g.defer=true; g.async=true; g.src=u+\'tracking.js\';
124
+ s.parentNode.insertBefore(g,s); })();
125
+ </script>', $this->data['HASHED_SHOPKEY']
126
+ );
127
+
128
+ return $addHeadJs;
129
+ }
130
+
131
+ /**
132
+ * Returns tracking js script for category page.
133
+ *
134
+ * @return string
135
+ */
136
+ private function categoryJs()
137
+ {
138
+ $currentCategory = Mage::getModel('catalog/layer')->getCurrentCategory();
139
+ $categoryJs = sprintf(
140
+ '<script type="text/javascript">
141
+ _paq.push([\'setEcommerceView\',
142
+ productSku = false,
143
+ productName = false,
144
+ category = [%s]
145
+ ]);
146
+ _paq.push([\'trackPageView\']);
147
+ </script>', $this->getCategoryPath($currentCategory->getPath())
148
+ );
149
+
150
+ return $categoryJs;
151
+ }
152
+
153
+ /**
154
+ * Returns tracking js script for checkout page.
155
+ *
156
+ * @return string
157
+ */
158
+ private function checkoutJs()
159
+ {
160
+ $lastOrderId = $this->data['LAST_ORDER_ID'];
161
+ /* @var $order Mage_Sales_Model_Order */
162
+ $order = Mage::getModel('sales/order')->load($lastOrderId);
163
+ if (!$order->getId()) {
164
+ return '';
165
+ }
166
+
167
+ $items = $order->getItemsCollection();
168
+ $checkoutJs = '<script type="text/javascript">';
169
+ foreach ($items as $item) {
170
+ $checkoutJs .= $this->getItemScript($item);
171
+ }
172
+
173
+ $checkoutJs .= sprintf(
174
+ '
175
+ _paq.push([\'trackEcommerceOrder\', "%s", %.2f, %.2f, %.2f, %.2f, %.2f ]);
176
+ _paq.push([\'trackPageView\']);
177
+ </script>', $order->getId(), $order->getGrandTotal(), $order->getSubtotal(), $order->getTaxAmount(), $order->getShippingAmount(), $order->getDiscountAmount()
178
+ );
179
+
180
+ return $checkoutJs;
181
+ }
182
+
183
+ /**
184
+ * Returns tracking js script for cart page.
185
+ *
186
+ * @return string
187
+ */
188
+ private function cartJs()
189
+ {
190
+ /* @var $cart Mage_Checkout_Helper_Cart */
191
+ $cartHelper = Mage::helper('checkout/cart');
192
+ /* @var $cart Mage_Checkout_Model_Cart */
193
+ $cart = $cartHelper->getCart();
194
+ $items = $cart->getItems();
195
+ $cartJs = '<script type="text/javascript">';
196
+ foreach ($items as $item) {
197
+ if ($item->getSpecialPrice() > 0 || $item->getPrice() > 0) {
198
+ $cartJs .= $this->getItemScript($item);
199
+ }
200
+ }
201
+
202
+ $cartJs .= sprintf('
203
+ _paq.push([\'trackEcommerceCartUpdate\', %.2f]);
204
+ _paq.push([\'trackPageView\']);
205
+ </script>',
206
+ $cart->getQuote()->getGrandTotal()
207
+ );
208
+
209
+ return $cartJs;
210
+ }
211
+
212
+ /**
213
+ * Returns tracking js script for product page.
214
+ *
215
+ * @return string
216
+ */
217
+ private function productJs($request)
218
+ {
219
+ $product_id = (int) $request->getParam('id');
220
+ $this->setProductData($product_id);
221
+
222
+ $productJs = sprintf(
223
+ '<script type="text/javascript">
224
+ _paq.push([\'setEcommerceView\',
225
+ "%s",
226
+ "%s",
227
+ [%s],
228
+ %s
229
+ ]);
230
+ _paq.push([\'trackPageView\']);
231
+ </script>', $this->data['PRODUCT_ORDERNUMBER'], addslashes($this->data['PRODUCT_TITLE']), $this->data['PRODUCT_CATEGORY_X'], $this->data['PRODUCT_PRICE']
232
+ );
233
+
234
+ return $productJs;
235
+ }
236
+
237
+ private function getItemScript($item)
238
+ {
239
+ return sprintf('
240
+ _paq.push([\'addEcommerceItem\',
241
+ "%s",
242
+ "%s",
243
+ [%s],
244
+ %.2f,
245
+ %d
246
+ ]);',
247
+ $item->getSku(),
248
+ addslashes($item->getName()),
249
+ $this->getCategoryPath($this->getFirstCategoryPath($item->getProduct()->getCategoryCollection())),
250
+ $item->getSpecialPrice() ?: $item->getPrice(),
251
+ $item->getQtyOrdered() ?: $item->getQty()
252
+ );
253
+ }
254
+
255
+ /**
256
+ * Get configuration data to start tracking
257
+ */
258
+ private function getConfData()
259
+ {
260
+ /** @var Mage_Customer_Model_Customer $customer */
261
+ /** @var Mage_Customer_Model_Session $session */
262
+ $session = Mage::getSingleton('customer/session');
263
+ $customer = $session->getCustomer();
264
+ $userGroup = Mage::getModel('customer/group')->load((int)$customer->getGroupId())->getCustomerGroupCode();
265
+ $shopKey = $this->getShopKey();
266
+ $userGroupHash = $this->userGroupToHash($shopKey, $userGroup);
267
+
268
+ $this->data['PLACEHOLDER_1'] = strtoupper(md5($shopKey));
269
+ $this->data['PLACEHOLDER_2'] = $session->isLoggedIn() ? $userGroupHash : '';
270
+ $this->data['HASHED_SHOPKEY'] = strtoupper(md5($shopKey));
271
+ }
272
+
273
+ /**
274
+ * @return string Reads plugin configuration and returns shop key for current shop.
275
+ */
276
+ private function getShopKey()
277
+ {
278
+ return Mage::getStoreConfig('findologic/findologic_group/shopkey', (int) Mage::app()->getStore()->getId());
279
+ }
280
+
281
+ /**
282
+ * Sets data for product tracking.
283
+ *
284
+ * @param integer $product_id
285
+ */
286
+ private function setProductData($product_id)
287
+ {
288
+ /* @var $product Mage_Catalog_Model_Product */
289
+ $product = Mage::getModel('catalog/product')->load($product_id);
290
+
291
+ $this->data['PRODUCT_ORDERNUMBER'] = $product->getSku();
292
+ $this->data['PRODUCT_TITLE'] = $product->getName();
293
+ $this->data['PRODUCT_CATEGORY_X'] = $this->getFirstCategoryPath($product->getCategoryCollection());
294
+ $this->data['PRODUCT_PRICE'] = sprintf('%.2f', $product->getSpecialPrice() ?: $product->getPrice());
295
+ }
296
+
297
+ /**
298
+ * Gets path of first active category from supplied array of categories.
299
+ *
300
+ * @param array $categories
301
+ * @return string Path for category
302
+ */
303
+ private function getFirstCategoryPath($categories)
304
+ {
305
+ foreach ($categories as $cat) {
306
+ $cat = $this->getCategory($cat->getId());
307
+ if ($cat->getIsActive()) {
308
+ return $this->getCategoryPath($cat->getPath());
309
+ }
310
+ }
311
+
312
+ return '';
313
+ }
314
+
315
+ /**
316
+ * Gets category path as string separated by provided separator.
317
+ * ** Helper function used in other helpers. **
318
+ *
319
+ * @param string $categoryPathIds Identifiers separated by slash. Example: 154/6584/653/8
320
+ * @param string $separator Separator for generated path between category names
321
+ * @param bool $wrap Indicates whether to wrap each category name with quotes
322
+
323
+ * @return string
324
+ */
325
+ public function getCategoryPath($categoryPathIds, $separator = ', ', $wrap = true, $addSlashes = true)
326
+ {
327
+ $holder = array();
328
+ $categoryIds = explode('/', $categoryPathIds);
329
+ $n = 0;
330
+ foreach ($categoryIds as $catId) {
331
+ // skip 'root' category and add up to 5 categories.
332
+ if (($n > 1 && $n <= 6)) {
333
+ $category = $this->getCategory($catId);
334
+ $categoryName = $addSlashes ? addslashes($category->getName()) : $category->getName();
335
+ $holder[] = $wrap ? '"' . $categoryName . '"' : $categoryName;
336
+ }
337
+
338
+ $n++;
339
+ }
340
+
341
+ return implode($separator, $holder);
342
+ }
343
+
344
+ /**
345
+ * Gets category from local cache.
346
+ *
347
+ * @param int $id Category identifier
348
+ * @return Mage_Catalog_Model_Category
349
+ */
350
+ public function getCategory($id)
351
+ {
352
+ if (!array_key_exists($id, self::$categories)) {
353
+ self::$categories[$id] = Mage::getResourceModel('catalog/category_collection')
354
+ ->addAttributeToSelect(array('is_active', 'name'))
355
+ ->addFieldToFilter('entity_id', $id)
356
+ ->getFirstItem();
357
+ }
358
+
359
+ return self::$categories[$id];
360
+ }
361
+
362
+ /**
363
+ * Returns hash key merged from shop key and user group.
364
+ * ** Helper function used in other helpers. **
365
+ *
366
+ * @param string $shopKey
367
+ * @param string $userGroup
368
+ *
369
+ * @return string
370
+ */
371
+ public function userGroupToHash($shopKey, $userGroup)
372
+ {
373
+ return base64_encode($shopKey ^ $userGroup);
374
+ }
375
+ }
app/code/community/FINDOLOGIC/OnSiteSearch/Helper/Xml.php ADDED
@@ -0,0 +1,123 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The MIT License (MIT)
4
+ *
5
+ * Copyright (c) 2016 FINDOLOGIC
6
+ *
7
+ * Permission is hereby granted, free of charge, to any person obtaining a
8
+ * copy of this software and associated documentation files (the "Software"),
9
+ * to deal in the Software without restriction, including without limitation
10
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11
+ * and/or sell copies of the Software, and to permit persons to whom
12
+ * the Software is furnished to do so, subject to the following conditions:
13
+ *
14
+ * The above copyright notice and this permission notice shall be included
15
+ * in all copies or substantial portions of the Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
18
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
19
+ * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
22
+ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+ */
24
+ use FINDOLOGIC_OnSiteSearch_Helper_XmlBasic as XmlBasic;
25
+ use FINDOLOGIC_OnSiteSearch_Helper_XmlGroup as XmlGroup;
26
+
27
+ class FINDOLOGIC_OnSiteSearch_Helper_Xml
28
+ {
29
+ /*
30
+ * string
31
+ */
32
+ private $shopKey;
33
+
34
+ /**
35
+ * Builds xml document.
36
+ *
37
+ * @param array $params
38
+ * @param array $products
39
+ * @return string Xml file
40
+ */
41
+ public function buildXmlDoc($params, $products)
42
+ {
43
+ $this->shopKey = $params['shopkey'];
44
+
45
+ $findologic = new SimpleXMLElement('<findologic/>');
46
+ $findologic->addAttribute('version', '1.0');
47
+ $items = $findologic->addChild('items');
48
+ $items->addAttribute('start', $params['start']);
49
+ $items->addAttribute('count', $params['count']);
50
+ $items->addAttribute('total', $params['total']);
51
+
52
+ /* @var FINDOLOGIC_OnSiteSearch_Helper_XmlBasic $xmlBasic */
53
+ $xmlBasic = Mage::helper('findologic/xmlBasic');
54
+ /** @var FINDOLOGIC_OnSiteSearch_Helper_TrackingScripts $helper */
55
+ $helper = Mage::helper('findologic/trackingScripts');
56
+
57
+ /* @var $product Mage_Catalog_Model_Product */
58
+ foreach ($products as $product) {
59
+ $item = $items->addChild('item');
60
+ $item->addAttribute('id', $product->getId());
61
+ $xmlBasic->setData($params, $product);
62
+ $this->renderItem($item, $product, $helper, $xmlBasic);
63
+ }
64
+
65
+ return $findologic->asXML();
66
+ }
67
+
68
+ /**
69
+ * Renders one product.
70
+ *
71
+ * @param SimpleXMLElement $item
72
+ * @param Mage_Catalog_Model_Product $product
73
+ * @param FINDOLOGIC_OnSiteSearch_Helper_TrackingScripts $helper
74
+ * @param FINDOLOGIC_OnSiteSearch_Helper_XmlBasic $xmlBasic
75
+ */
76
+ private function renderItem(SimpleXMLElement $item, Mage_Catalog_Model_Product $product, $helper, $xmlBasic)
77
+ {
78
+ $xmlBasic->renderOrderNumber($item->addChild('allOrdernumbers'), $product);
79
+
80
+ $xmlBasic->renderName($item->addChild('names'), $product);
81
+
82
+ $xmlBasic->renderSummary($item->addChild('summaries'), $product);
83
+
84
+ $xmlBasic->renderDescription($item->addChild('descriptions'), $product);
85
+
86
+ $xmlBasic->renderPrice($item->addChild('prices'), $product);
87
+
88
+ $xmlBasic->renderUrl($item->addChild('urls'), $product);
89
+
90
+ $xmlBasic->renderImages($item->addChild('allImages'), $product);
91
+
92
+ $xmlBasic->renderAttributes($item->addChild('allAttributes'), $product);
93
+
94
+ $xmlBasic->renderKeywords($item->addChild('allKeywords'), $product);
95
+
96
+ // By default product visibility can be set only for different stores, not for user group, so we render all groups.
97
+ $userGroups = $item->addChild('usergroups');
98
+ $groups = Mage::getModel('customer/group')->getCollection();
99
+ /** @var Mage_Customer_Model_Group $group */
100
+ foreach($groups as $group) {
101
+ if ($group->getId() > 0) {
102
+ $this->appendCData($userGroups->addChild('usergroup'), $helper->userGroupToHash($this->shopKey, $group->getCustomerGroupCode()));
103
+ }
104
+ }
105
+
106
+ $xmlBasic->renderSalesFrequency($item->addChild('salesFrequencies'), $product);
107
+
108
+ $xmlBasic->renderDateAdded($item->addChild('dateAddeds'), $product);
109
+
110
+ $xmlBasic->renderAllProperties($item->addChild('allProperties'), $product);
111
+ }
112
+
113
+ private function appendCData(SimpleXMLElement $node, $text)
114
+ {
115
+ $domNode = dom_import_simplexml($node);
116
+ $domNode->appendChild($domNode->ownerDocument->createCDATASection($this->utf8Replace($text)));
117
+ }
118
+
119
+ private function utf8Replace($text)
120
+ {
121
+ return preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F\x80-\x9F]/u', '', trim($text));
122
+ }
123
+ }
app/code/community/FINDOLOGIC/OnSiteSearch/Helper/XmlBasic.php ADDED
@@ -0,0 +1,579 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The MIT License (MIT)
4
+ *
5
+ * Copyright (c) 2016 FINDOLOGIC
6
+ *
7
+ * Permission is hereby granted, free of charge, to any person obtaining a
8
+ * copy of this software and associated documentation files (the "Software"),
9
+ * to deal in the Software without restriction, including without limitation
10
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11
+ * and/or sell copies of the Software, and to permit persons to whom
12
+ * the Software is furnished to do so, subject to the following conditions:
13
+ *
14
+ * The above copyright notice and this permission notice shall be included
15
+ * in all copies or substantial portions of the Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
18
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
19
+ * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
22
+ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+ */
24
+ class FINDOLOGIC_OnSiteSearch_Helper_XmlBasic extends Mage_Core_Helper_Abstract
25
+ {
26
+ /**
27
+ * @var string
28
+ */
29
+ private $shopKey;
30
+
31
+ /**
32
+ * @var int
33
+ */
34
+ private $storeId;
35
+
36
+ /**
37
+ * @var int
38
+ */
39
+ private $rootCategoryId;
40
+
41
+ /**
42
+ * @var Mage_Catalog_Model_Product
43
+ */
44
+ private $product;
45
+
46
+ /**
47
+ * @var array[Mage_Catalog_Model_Product]
48
+ */
49
+ private $variations;
50
+
51
+ private static $customerGroups = array();
52
+ private static $baseUrl;
53
+ private static $mediaHelper;
54
+
55
+ /**
56
+ * Static function that initializes all static fields to enchance performance
57
+ */
58
+ private static function initStaticFields()
59
+ {
60
+ if (empty(self::$customerGroups)) {
61
+ /* @var $collection Mage_Customer_Model_Resource_Group_Collection */
62
+ $collection = Mage::getResourceModel('customer/group_collection');
63
+ foreach ($collection as $group) {
64
+ self::$customerGroups[$group->getId()] = $group->getCustomerGroupCode();
65
+ }
66
+
67
+ self::$baseUrl = Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_WEB);
68
+ self::$mediaHelper = Mage::getModel('catalog/product_media_config');
69
+ }
70
+ }
71
+
72
+ /**
73
+ * Sets data needed for all the methods. This method must be called before all other methods.
74
+ *
75
+ * @param array $params
76
+ * @param Mage_Catalog_Model_Product $product
77
+ * @return FINDOLOGIC_OnSiteSearch_Helper_XmlBasic
78
+ */
79
+ public function setData($params, Mage_Catalog_Model_Product $product)
80
+ {
81
+ self::initStaticFields();
82
+ $this->shopKey = $params['shopkey'];
83
+ $this->storeId = $params['storeId'];
84
+ $this->rootCategoryId = Mage::app()->getStore($this->storeId)->getRootCategoryId();
85
+ $this->product = $product;
86
+ $this->variations = array();
87
+ if ($product && $product->isConfigurable()) {
88
+ $variations = $product->getTypeInstance(true)->getUsedProducts(null, $product);
89
+ $variationIds = array();
90
+ foreach ($variations as $variation) {
91
+ if ($variation->isAvailable()) {
92
+ $variationIds[] = $variation->getId();
93
+ }
94
+ }
95
+
96
+ $collection = Mage::getResourceModel('catalog/product_collection')
97
+ ->setStoreId($params['storeId'])
98
+ ->addAttributeToSelect('*')
99
+ ->addAttributeToFilter('entity_id', array('in' => $variationIds));
100
+
101
+ foreach ($collection as $variation) {
102
+ $this->variations[] = $variation;
103
+ }
104
+ }
105
+
106
+ return $this;
107
+ }
108
+
109
+ /**
110
+ * Renders order numbers.
111
+ *
112
+ * @param SimpleXMLElement $allOrderNumbers
113
+ */
114
+ public function renderOrderNumber(SimpleXMLElement $allOrderNumbers)
115
+ {
116
+ $orderNumbers = $allOrderNumbers->addChild('ordernumbers');
117
+ $this->appendCData($orderNumbers->addChild('ordernumber'), $this->product->getSku());
118
+
119
+ /* @var $variation Mage_Catalog_Model_Product */
120
+ foreach ($this->variations as $variation) {
121
+ if ($variation->isAvailable()) {
122
+ $this->appendCData($orderNumbers->addChild('ordernumber'), $variation->getSku());
123
+ }
124
+ }
125
+ }
126
+
127
+ /**
128
+ * Renders name.
129
+ *
130
+ * @param SimpleXMLElement $names
131
+ */
132
+ public function renderName(SimpleXMLElement $names)
133
+ {
134
+ $this->appendCData($names->addChild('name'), $this->product->getName());
135
+ }
136
+
137
+ /**
138
+ * Renders summary (short description).
139
+ *
140
+ * @param SimpleXMLElement $summaries
141
+ */
142
+ public function renderSummary(SimpleXMLElement $summaries)
143
+ {
144
+ $this->appendCData($summaries->addChild('summary'), $this->product->getShortDescription());
145
+ }
146
+
147
+ /**
148
+ * Renders long description.
149
+ *
150
+ * @param SimpleXMLElement $descriptions
151
+ */
152
+ public function renderDescription(SimpleXMLElement $descriptions)
153
+ {
154
+ $this->appendCData($descriptions->addChild('description'), $this->product->getDescription());
155
+ }
156
+
157
+ /**
158
+ * Renders price.
159
+ *
160
+ * @param SimpleXMLElement $prices
161
+ */
162
+ public function renderPrice(SimpleXMLElement $prices)
163
+ {
164
+ $specialPrice = $this->getSpecialPrice();
165
+ $price = $specialPrice > 0 ? $specialPrice : $this->product->getPrice();
166
+
167
+ $groupPrices = $this->getGroupPrices($this->product);
168
+ /** @var Mage_Catalog_Model_Product $variation */
169
+ foreach ($this->variations as $variation) {
170
+ $price = min($price, ($variation->getSpecialPrice() ?: $variation->getPrice()));
171
+ $groupPrices = array_merge_recursive($groupPrices, $this->getGroupPrices($variation));
172
+ }
173
+
174
+ $this->appendCData($prices->addChild('price'), sprintf('%.2f', $price));
175
+
176
+ foreach ($groupPrices as $code => $priceArray) {
177
+ $priceNode = $prices->addChild('price');
178
+ $this->appendCData($priceNode, sprintf('%.2f', min($priceArray)));
179
+ $priceNode->addAttribute('usergroup', $code);
180
+ }
181
+ }
182
+
183
+ private function getGroupPrices(Mage_Catalog_Model_Product $product)
184
+ {
185
+ /** @var FINDOLOGIC_OnSiteSearch_Helper_TrackingScripts $helper */
186
+ $helper = Mage::helper('findologic/trackingScripts');
187
+
188
+ $attribute = $product->getResource()->getAttribute('group_price');
189
+ $attribute->getBackend()->afterLoad($this->product);
190
+ $groupPrices = $product->getData('group_price');
191
+
192
+ $result = array();
193
+ if ($groupPrices) {
194
+ foreach ($groupPrices as $group) {
195
+ $userGroup = self::$customerGroups[$group['cust_group']];
196
+ $result[$helper->userGroupToHash($this->shopKey, $userGroup)] = array($group['price']);
197
+ }
198
+ }
199
+
200
+ return $result;
201
+ }
202
+
203
+ /**
204
+ * Render URL.
205
+ *
206
+ * @param SimpleXMLElement $urls
207
+ */
208
+ public function renderUrl(SimpleXMLElement $urls)
209
+ {
210
+ $this->appendCData($urls->addChild('url'), $this->product->getProductUrl());
211
+ }
212
+
213
+ /**
214
+ * Renders all images.
215
+ *
216
+ * @param SimpleXMLElement $allImages
217
+ */
218
+ public function renderImages(SimpleXMLElement $allImages)
219
+ {
220
+ $resource = Mage::getSingleton('core/resource');
221
+ $readConnection = $resource->getConnection('core_read');
222
+ $mediaGallery = $resource->getTableName('catalog/product') . '_media_gallery';
223
+ $mediaGalleryValue = $mediaGallery . '_value';
224
+ $query = "SELECT g.value FROM $mediaGallery g
225
+ LEFT JOIN $mediaGalleryValue AS v ON v.value_id = g.value_id
226
+ WHERE g.entity_id = {$this->product->getId()} AND v.disabled = 0 ORDER BY v.position";
227
+ $results = $readConnection->fetchAll($query);
228
+
229
+ $images = $allImages->addChild('images');
230
+ if (count($results) > 0) {
231
+ foreach ($results as $item) {
232
+ $this->appendCData($images->addChild('image'), self::$mediaHelper->getMediaUrl($item['value']));
233
+ }
234
+ } else {
235
+ $image = $this->product->getImage();
236
+ if ($image && $image != 'no_selection') {
237
+ $this->appendCData($images->addChild('image'), Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_MEDIA) . 'catalog/product' . $this->product->getImage());
238
+ } else {
239
+ $this->appendCData($images->addChild('image'), Mage::getSingleton('catalog/product_media_config')->getBaseMediaUrl()
240
+ . '/placeholder/' . Mage::getStoreConfig('catalog/placeholder/small_image_placeholder'));
241
+ }
242
+ }
243
+ }
244
+
245
+ /**
246
+ * Renders all attributes (categories, categories url).
247
+ *
248
+ * @param SimpleXMLElement $allAttributes
249
+ */
250
+ public function renderAttributes(SimpleXMLElement $allAttributes)
251
+ {
252
+ $attributesNode = $allAttributes->addChild('attributes');
253
+ $this->renderCategories($attributesNode);
254
+
255
+ $this->addAttributes($attributesNode);
256
+
257
+ $this->removeEmptyNode($attributesNode, $attributesNode);
258
+ }
259
+
260
+ /**
261
+ * Renders categories and category urls as attributes.
262
+ *
263
+ * @param SimpleXMLElement $attributesNode
264
+ * @param array [Mage_Catalog_Model_Category] $catCollection
265
+ */
266
+ private function renderCategories($attributesNode)
267
+ {
268
+ $catCollection = $this->getCategories();
269
+
270
+ if (count($catCollection) === 0) {
271
+ return;
272
+ }
273
+
274
+ $catNode = $attributesNode->addChild('attribute');
275
+
276
+ $this->appendCData($catNode->addChild('key'), 'cat');
277
+ $valuesNode = $catNode->addChild('values');
278
+
279
+ $catUrlNode = $attributesNode->addChild('attribute');
280
+ $this->appendCData($catUrlNode->addChild('key'), 'cat_url');
281
+ $valuesCatUrl = $catUrlNode->addChild('values');
282
+
283
+ /** @var FINDOLOGIC_OnSiteSearch_Helper_TrackingScripts $helper */
284
+ $helper = Mage::helper('findologic/trackingScripts');
285
+
286
+ /** @var Mage_Catalog_Model_Category $cat */
287
+ foreach ($catCollection as $cat) {
288
+ $cat = $helper->getCategory($cat->getId());
289
+
290
+ if ($cat->getIsActive()) {
291
+ $catPath = $helper->getCategoryPath($cat->getPath(), '_', false, false);
292
+ if ($catPath) {
293
+ $this->appendCData($valuesNode->addChild('value'), $catPath);
294
+ $cat_url = parse_url($cat->getUrl());
295
+ $valuesCatUrl->addChild('value', $cat_url['path']);
296
+ }
297
+ }
298
+ }
299
+
300
+ $this->removeEmptyNode($valuesNode, $catNode);
301
+ $this->removeEmptyNode($valuesCatUrl, $catUrlNode);
302
+ }
303
+
304
+ /**
305
+ * Filter categories by rootCategoryId
306
+ *
307
+ * @return array $collection
308
+ */
309
+ private function getCategories()
310
+ {
311
+ $collection = Mage::getResourceModel('catalog/category_collection')
312
+ ->joinField('product_id',
313
+ 'catalog/category_product',
314
+ 'product_id',
315
+ 'category_id = entity_id',
316
+ null)
317
+ ->addFieldToFilter('product_id', (int)$this->product->getId())
318
+ ->addFieldToFilter('path', array('like'=> "1/$this->rootCategoryId/%"));
319
+ return $collection;
320
+ }
321
+
322
+ /**
323
+ * Adds all configurable attributes as SimpleXMLElement array.
324
+ */
325
+ private function addAttributes(SimpleXMLElement $attributesNode)
326
+ {
327
+ /* @var Mage_Eav_Model_Entity_Attribute $attribute */
328
+ /* @var $variation Mage_Catalog_Model_Product */
329
+ $result = array();
330
+ $this->addAttributesForProduct($result, $this->product);
331
+
332
+ foreach ($this->variations as $variation) {
333
+ $this->addAttributesForProduct($result, $variation);
334
+ }
335
+
336
+ if ($this->variations) {
337
+ $productAttributes = $this->product->getTypeInstance()->getConfigurableAttributes();
338
+ foreach ($productAttributes as $attribute) {
339
+ $attributeCode = $attribute->getProductAttribute()->getAttributeCode();
340
+ $values = array();
341
+ foreach ($this->variations as $variation) {
342
+ if ($variation->isAvailable()) {
343
+ $attributeValue = trim($variation->getAttributeText($attributeCode));
344
+ if ($attributeValue && array_search($attributeValue, $values) === false) {
345
+ $values[] = $attributeValue;
346
+ }
347
+ }
348
+ }
349
+
350
+ if (count($values)) {
351
+ $result[$attributeCode] = $values;
352
+ }
353
+ }
354
+ }
355
+
356
+ foreach ($result as $attrKey => $attrValues) {
357
+ if (!$attrValues) {
358
+ continue;
359
+ }
360
+
361
+ $attributeNode = $attributesNode->addChild('attribute');
362
+ $this->appendCData($attributeNode->addChild('key'), $attrKey);
363
+ $valuesNode = $attributeNode->addChild('values');
364
+ foreach ($attrValues as $value) {
365
+ $this->appendCData($valuesNode->addChild('value'), $value);
366
+ }
367
+ }
368
+ }
369
+
370
+ /**
371
+ * @param array $result
372
+ * @param Mage_Catalog_Model_Product $product
373
+ */
374
+ private function addAttributesForProduct(&$result, $product)
375
+ {
376
+ /* @var Mage_Eav_Model_Entity_Attribute $attribute */
377
+ $attributes = $product->getAttributes();
378
+ foreach ($attributes as $attribute) {
379
+ if ($attribute->getIsFilterable() || $attribute->getIsFilterableInSearch()) {
380
+ $code = $attribute->getAttributeCode();
381
+ $value = trim($product->getAttributeText($code));
382
+ if (!array_key_exists($code, $result)) {
383
+ $result[$code] = array();
384
+ }
385
+
386
+ if ($value && array_search($value, $result[$code]) === false) {
387
+ $result[$code][] = $value;
388
+ }
389
+ }
390
+ }
391
+ }
392
+
393
+ /**
394
+ * Renders all keywords (meta keywords).
395
+ *
396
+ * @param SimpleXMLElement $allKeywords
397
+ */
398
+ public function renderKeywords(SimpleXMLElement $allKeywords)
399
+ {
400
+ $metaKeywords = $this->product->getMetaKeyword();
401
+ if ($metaKeywords) {
402
+ $metaKeywords = explode(',', $metaKeywords);
403
+ $keywords = $allKeywords->addChild('keywords');
404
+
405
+ if (count($metaKeywords)) {
406
+ foreach ($metaKeywords as $keyword) {
407
+ $keyword = trim($keyword);
408
+ if ($keyword !== '') {
409
+ $this->appendCData($keywords->addChild('keyword'), $keyword);
410
+ }
411
+ }
412
+ } else {
413
+ $keywords->addChild('keyword');
414
+ }
415
+ }
416
+ }
417
+
418
+ /**
419
+ * Renders date added.
420
+ *
421
+ * @param SimpleXMLElement $dateAdded
422
+ */
423
+ public function renderDateAdded(SimpleXMLElement $dateAdded)
424
+ {
425
+ $format = 'Y-m-d H:i:s';
426
+ /* @var $date DateTime */
427
+ $date = DateTime::createFromFormat($format, $this->product->getCreatedAt());
428
+
429
+ $this->appendCData($dateAdded->addChild('dateAdded'), $date->format(DATE_ATOM));
430
+ }
431
+
432
+ /**
433
+ * Render sales frequencies.
434
+ *
435
+ * @param SimpleXMLElement $salesFrequencies
436
+ */
437
+ public function renderSalesFrequency(SimpleXMLElement $salesFrequencies)
438
+ {
439
+ $prefix = Mage::getConfig()->getTablePrefix();
440
+
441
+ // Get all orders filter by product_id
442
+ $groupOrders = Mage::getResourceModel('sales/order_item_collection')
443
+ ->addAttributeToFilter('product_id', (int)$this->product->getId());
444
+
445
+ // get only orders from customers belonging to a group
446
+ $groupOrders->getSelect()
447
+ ->joinLeft(
448
+ array('sfo' => $prefix . 'sales_flat_order'),
449
+ 'order_id=' . 'sfo.entity_id',
450
+ array('sfo.customer_group_id', 'sfo.increment_id')
451
+ )
452
+ ->join(
453
+ array('cg' => $prefix . 'customer_group'),
454
+ 'sfo.customer_group_id=' . 'cg.customer_group_id',
455
+ array('cg.customer_group_code')
456
+ )
457
+ ->where('sfo.customer_group_id > 0');
458
+
459
+ $groupOrders = $groupOrders->load();
460
+
461
+ $salesFrequenciesCountPerGroup = array();
462
+ $userGroupArr = array();
463
+ $salesFrequenciesCount = 0;
464
+
465
+ /** @var FINDOLOGIC_OnSiteSearch_Helper_TrackingScripts $helper */
466
+ $helper = Mage::helper('findologic/trackingScripts');
467
+
468
+ /* @var $order Mage_Sales_Model_Order */
469
+ foreach ($groupOrders as $order) {
470
+ $userGroup = $order->getCustomerGroupCode();
471
+ $userGroupHash = $helper->userGroupToHash($this->shopKey, $userGroup);
472
+
473
+ $num = array_search($userGroupHash, $userGroupArr);
474
+ if ($num !== false) {
475
+ $salesFrequenciesCountPerGroup[$userGroupHash] += 1;
476
+ } else {
477
+ $userGroupArr[] = $userGroupHash;
478
+ $salesFrequenciesCountPerGroup[$userGroupHash] = 1;
479
+ }
480
+
481
+ $salesFrequenciesCount++;
482
+ }
483
+
484
+ $orders = Mage::getResourceModel('sales/order_item_collection')
485
+ ->addAttributeToFilter('product_id', (int)$this->product->getId());
486
+
487
+ // Condition: custom group "NOT LOGGED IN" and Group doesn't exists anymore (if group is deleted).
488
+ $orders->getSelect()
489
+ ->join(
490
+ array('sfo' => $prefix . 'sales_flat_order'), 'order_id=' . 'sfo.entity_id', array('sfo.customer_group_id', 'sfo.increment_id')
491
+ )
492
+ ->joinLeft(
493
+ array('cg' => $prefix . 'customer_group'), 'sfo.customer_group_id=' . 'cg.customer_group_id', array('cg.customer_group_code')
494
+ )
495
+ ->where('cg.customer_group_code is null OR sfo.customer_group_id = 0');
496
+
497
+ $salesFrequenciesCount += $orders->getSize();
498
+
499
+ if ($salesFrequenciesCount > 0) {
500
+ $this->appendCData($salesFrequencies->addChild('salesFrequency'), $salesFrequenciesCount);
501
+ }
502
+
503
+ if (count($salesFrequenciesCountPerGroup) > 0) {
504
+ foreach ($salesFrequenciesCountPerGroup as $key => $value) {
505
+ $salesNode = $salesFrequencies->addChild('salesFrequency');
506
+ $this->appendCData($salesNode, $value);
507
+ $salesNode->addAttribute('usergroup', $key);
508
+ }
509
+ }
510
+ }
511
+
512
+ /**
513
+ * Renders all properties.
514
+ *
515
+ * @param SimpleXMLElement $allProperties
516
+ */
517
+ public function renderAllProperties(SimpleXMLElement $allProperties)
518
+ {
519
+ $properties = $allProperties->addChild('properties');
520
+
521
+ $quantity = (int)$this->product->getStockItem()->getQty() + (int)$this->product->getQty();
522
+ foreach ($this->variations as $variation) {
523
+ $quantity += (int)$variation->getStockItem()->getQty() + (int)$variation->getQty();
524
+ }
525
+
526
+ $productProperties = array(
527
+ 'base price' => sprintf('%.2f', $this->product->getPrice()),
528
+ 'special price' => sprintf('%.2f', $this->getSpecialPrice()),
529
+ 'quantity' => $quantity,
530
+ );
531
+
532
+ foreach ($productProperties as $key => $propertyValue) {
533
+ $property = $properties->addChild('property');
534
+ $this->appendCData($property->addChild('key'), $key);
535
+ $this->appendCData($property->addChild('value'), $propertyValue);
536
+ }
537
+ }
538
+
539
+ /**
540
+ * @return float
541
+ */
542
+ private function getSpecialPrice()
543
+ {
544
+ $curDate = strtotime(date('Y-m-d'));
545
+ $dateTo = strtotime($this->product->getSpecialToDate());
546
+ $dateFrom = strtotime($this->product->getSpecialFromDate());
547
+ $specialPrice = $this->product->getPrice();
548
+ $priceRule = Mage::getModel('catalogrule/rule')->calcProductPriceRule($this->product, $this->product->getPrice())?Mage::getModel('catalogrule/rule')->calcProductPriceRule($this->product, $this->product->getPrice()):$this->product->getPrice();
549
+
550
+ if ($curDate <= $dateTo && $curDate >= $dateFrom) {
551
+ $specialPrice = $this->product->getSpecialPrice();
552
+ }
553
+
554
+ if ($specialPrice < $priceRule) {
555
+ return $specialPrice;
556
+ }
557
+
558
+ return $priceRule < $this->product->getPrice() ? $priceRule : 0;
559
+ }
560
+
561
+ private function appendCData(SimpleXMLElement $node, $text)
562
+ {
563
+ $domNode = dom_import_simplexml($node);
564
+ $domNode->appendChild($domNode->ownerDocument->createCDATASection($this->utf8Replace($text)));
565
+ }
566
+
567
+ private function utf8Replace($text)
568
+ {
569
+ return preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F\x80-\x9F]/u', '', trim($text));
570
+ }
571
+
572
+ private function removeEmptyNode($node, $relatedNode)
573
+ {
574
+ if (!$node->children()->asXML()) {
575
+ $dom = dom_import_simplexml($relatedNode);
576
+ $dom->parentNode->removeChild($dom);
577
+ }
578
+ }
579
+ }
app/code/community/FINDOLOGIC/OnSiteSearch/Model/Observer.php ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The MIT License (MIT)
4
+ *
5
+ * Copyright (c) 2016 FINDOLOGIC
6
+ *
7
+ * Permission is hereby granted, free of charge, to any person obtaining a
8
+ * copy of this software and associated documentation files (the "Software"),
9
+ * to deal in the Software without restriction, including without limitation
10
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11
+ * and/or sell copies of the Software, and to permit persons to whom
12
+ * the Software is furnished to do so, subject to the following conditions:
13
+ *
14
+ * The above copyright notice and this permission notice shall be included
15
+ * in all copies or substantial portions of the Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
18
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
19
+ * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
22
+ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+ */
24
+ class FINDOLOGIC_OnSiteSearch_Model_Observer {
25
+
26
+ public function onAfterGetSearchResult(Varien_Event_Observer $eventData)
27
+ {
28
+ // need to get proper number of items if possible
29
+ }
30
+
31
+ public function onCheckoutOnepageControllerSuccess(Varien_Event_Observer $event)
32
+ {
33
+ $data = $event->getData();
34
+ Mage::helper('findologic/trackingScripts')->setLastOrderId(reset($data['order_ids']));
35
+ }
36
+ }
app/code/community/FINDOLOGIC/OnSiteSearch/Model/ShopkeyValidation.php ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The MIT License (MIT)
4
+ *
5
+ * Copyright (c) 2016 FINDOLOGIC
6
+ *
7
+ * Permission is hereby granted, free of charge, to any person obtaining a
8
+ * copy of this software and associated documentation files (the "Software"),
9
+ * to deal in the Software without restriction, including without limitation
10
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11
+ * and/or sell copies of the Software, and to permit persons to whom
12
+ * the Software is furnished to do so, subject to the following conditions:
13
+ *
14
+ * The above copyright notice and this permission notice shall be included
15
+ * in all copies or substantial portions of the Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
18
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
19
+ * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
22
+ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+ */
24
+ class FINDOLOGIC_OnSiteSearch_Model_ShopkeyValidation extends Mage_Core_Model_Config_Data
25
+ {
26
+ /**
27
+ * Saves object data.
28
+ *
29
+ * @return FINDOLOGIC_OnSiteSearch_Model_ShopkeyValidation
30
+ */
31
+ public function save()
32
+ {
33
+ $shopKey = trim($this->getValue());
34
+ if ($shopKey) {
35
+ $code = Mage::getSingleton('adminhtml/config_data')->getStore();
36
+ $currentId = Mage::getModel('core/store')->load($code)->getId();
37
+
38
+ $stores = Mage::app()->getStores();
39
+
40
+ foreach ($stores as $store) {
41
+ $storeId = $store->getId();
42
+ $keyValue = Mage::getStoreConfig('findologic/findologic_group/shopkey', $storeId);
43
+
44
+ if ($keyValue === $shopKey && $currentId !== $storeId) {
45
+ Mage::throwException('Shop key already exists! Each store view must have its own shop key.');
46
+ }
47
+ }
48
+
49
+ $this->setValue(trim($shopKey));
50
+ }
51
+
52
+ return parent::save();
53
+ }
54
+ }
app/code/community/FINDOLOGIC/OnSiteSearch/controllers/ExportController.php ADDED
@@ -0,0 +1,221 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The MIT License (MIT)
4
+ *
5
+ * Copyright (c) 2016 FINDOLOGIC
6
+ *
7
+ * Permission is hereby granted, free of charge, to any person obtaining a
8
+ * copy of this software and associated documentation files (the "Software"),
9
+ * to deal in the Software without restriction, including without limitation
10
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11
+ * and/or sell copies of the Software, and to permit persons to whom
12
+ * the Software is furnished to do so, subject to the following conditions:
13
+ *
14
+ * The above copyright notice and this permission notice shall be included
15
+ * in all copies or substantial portions of the Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
18
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
19
+ * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
22
+ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+ */
24
+ use FINDOLOGIC_OnSiteSearch_Helper_Xml as Xml;
25
+
26
+ class FINDOLOGIC_OnSiteSearch_ExportController extends Mage_Core_Controller_Front_Action
27
+ {
28
+ /**
29
+ * @var string
30
+ */
31
+ private $shopKey;
32
+
33
+ /**
34
+ * @var int
35
+ */
36
+ private $storeId;
37
+
38
+ /**
39
+ * @var int
40
+ */
41
+ private $count;
42
+
43
+ /**
44
+ * @var int
45
+ */
46
+ private $start;
47
+
48
+ /**
49
+ * @var int
50
+ */
51
+ private $total;
52
+
53
+ /**
54
+ * Exports data using shop key.
55
+ */
56
+ public function indexAction()
57
+ {
58
+ $request = $this->getRequest();
59
+ $this->shopKey = $request->getParam('shopkey', false);
60
+ $this->start = $request->getParam('start', false);
61
+ $this->count = $request->getParam('count', false);
62
+ $this->storeId = $this->getStoreId($this->shopKey);
63
+
64
+ $this->validateInput();
65
+
66
+ $products = $this->getAllValidProducts();
67
+ $xml = $this->createXml($products);
68
+
69
+ if ($request->getParam('validate', false)) {
70
+ $this->validateXml($xml);
71
+ }
72
+
73
+ header('Content-Type: application/xml; charset=utf-8');
74
+ echo $xml;
75
+ die;
76
+ }
77
+
78
+ /**
79
+ * Validates whether all input parameters are supplied.
80
+ *
81
+ */
82
+ private function validateInput()
83
+ {
84
+ $message = '';
85
+ if (!$this->shopKey) {
86
+ $message = 'Parameter "shopkey" is missing! ';
87
+ }
88
+
89
+ if (!$this->storeId) {
90
+ $message .= 'Parameter "shopkey" is not configured for any store! ';
91
+ }
92
+
93
+ if ($this->start === false || $this->start < 0) {
94
+ $message .= 'Parameter "start" is missing or less than 0! ';
95
+ }
96
+
97
+ if (!$this->count || $this->count < 01) {
98
+ $message .= 'Parameter "count" is missing or less than 1!';
99
+ }
100
+
101
+ if ($message) {
102
+ die($message);
103
+ }
104
+ }
105
+
106
+ private function validateXml($xml)
107
+ {
108
+ // Enable user error handling
109
+ libxml_use_internal_errors(true);
110
+
111
+ $dom = new DOMDocument();
112
+ $dom->loadXML($xml);
113
+ $path = 'https://raw.githubusercontent.com/FINDOLOGIC/xml-export/master/src/main/resources/findologic.xsd';
114
+ if (!$dom->schemaValidate($path)) {
115
+ $errors = libxml_get_errors();
116
+ foreach ($errors as $error) {
117
+ $return = "<br/>\n";
118
+ switch ($error->level) {
119
+ case LIBXML_ERR_WARNING:
120
+ $return .= "<b>Warning $error->code</b>: ";
121
+ break;
122
+ case LIBXML_ERR_ERROR:
123
+ $return .= "<b>Error $error->code</b>: ";
124
+ break;
125
+ case LIBXML_ERR_FATAL:
126
+ $return .= "<b>Fatal Error $error->code</b>: ";
127
+ break;
128
+ }
129
+
130
+ $return .= trim($error->message);
131
+ if ($error->file) {
132
+ $return .= " in <b>$error->file</b>";
133
+ }
134
+
135
+ echo $return . " on line <b>$error->line</b>\n";
136
+ }
137
+
138
+ die;
139
+ }
140
+ }
141
+
142
+ /**
143
+ * Get store id for specified shop key.
144
+ * @param string $shopKey
145
+ * @return boolean|integer store id if found; otherwise, false.
146
+ */
147
+ private function getStoreId($shopKey)
148
+ {
149
+ $stores = Mage::app()->getStores();
150
+ foreach ($stores as $store) {
151
+ $storeId = $store->getId();
152
+ $keyValue = Mage::getStoreConfig('findologic/findologic_group/shopkey', $storeId);
153
+
154
+ if ($keyValue === $shopKey) {
155
+ return $storeId;
156
+ }
157
+ }
158
+
159
+ return false;
160
+ }
161
+
162
+ /**
163
+ * Get all products that passed validation for current selected store.
164
+ *
165
+ * @return array $productsCollection
166
+ */
167
+ private function getAllValidProducts()
168
+ {
169
+ /* @var $productsCollection Mage_Catalog_Model_Resource_Product_Collection */
170
+ $productsCollection = Mage::getResourceModel('catalog/product_collection');
171
+ $productsCollection
172
+ ->setStoreId($this->storeId)
173
+ ->addStoreFilter($this->storeId)
174
+ ->addAttributeToSelect('*')
175
+ ->addAttributeToFilter('status', Mage_Catalog_Model_Product_Status::STATUS_ENABLED)
176
+ ->addAttributeToFilter('visibility', array('in' => array(
177
+ Mage_Catalog_Model_Product_Visibility::VISIBILITY_IN_SEARCH,
178
+ Mage_Catalog_Model_Product_Visibility::VISIBILITY_IN_CATALOG,
179
+ Mage_Catalog_Model_Product_Visibility::VISIBILITY_BOTH,
180
+ )))
181
+ ->joinField(
182
+ 'qty',
183
+ 'cataloginventory/stock_item',
184
+ 'qty',
185
+ 'product_id = entity_id',
186
+ 'is_in_stock = 1',
187
+ 'left'
188
+ );
189
+
190
+ $productsCollection->getSelect()
191
+ ->where("IF(e.type_id != '" . Mage_Catalog_Model_Product_Type::TYPE_SIMPLE . "', at_qty.qty = 0, at_qty.qty > 0)");
192
+
193
+ // condition missing: An article only found in a hidden category should not be exported. Performance issue with this.
194
+
195
+ $this->total = $productsCollection->getSize();
196
+
197
+ $productsCollection->getSelect()
198
+ ->limit($this->count, $this->start);
199
+
200
+ return $productsCollection;
201
+ }
202
+
203
+ /**
204
+ * Create XML file.
205
+ * @param array $products
206
+ */
207
+ private function createXml($products)
208
+ {
209
+ $xml = new Xml();
210
+ return $xml->buildXmlDoc(
211
+ array(
212
+ 'storeId' => $this->storeId,
213
+ 'shopkey' => $this->shopKey,
214
+ 'count' => $this->count,
215
+ 'start' => $this->start,
216
+ 'total' => $this->total,
217
+ ),
218
+ $products
219
+ );
220
+ }
221
+ }
app/code/community/FINDOLOGIC/OnSiteSearch/etc/adminhtml.xml ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!--
3
+ * The MIT License (MIT)
4
+ *
5
+ * Copyright (c) 2016 FINDOLOGIC
6
+ *
7
+ * Permission is hereby granted, free of charge, to any person obtaining a
8
+ * copy of this software and associated documentation files (the "Software"),
9
+ * to deal in the Software without restriction, including without limitation
10
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11
+ * and/or sell copies of the Software, and to permit persons to whom
12
+ * the Software is furnished to do so, subject to the following conditions:
13
+ *
14
+ * The above copyright notice and this permission notice shall be included
15
+ * in all copies or substantial portions of the Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
18
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
19
+ * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
22
+ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+ -->
24
+ <config>
25
+ <acl>
26
+ <resources>
27
+ <admin>
28
+ <children>
29
+ <system>
30
+ <children>
31
+ <config>
32
+ <children>
33
+ <findologic translate="title">
34
+ <title>FINDOLOGIC OnSiteSearch</title>
35
+ <sort_order>1000</sort_order>
36
+ </findologic>
37
+ </children>
38
+ </config>
39
+ </children>
40
+ </system>
41
+ </children>
42
+ </admin>
43
+ </resources>
44
+ </acl>
45
+ </config>
app/code/community/FINDOLOGIC/OnSiteSearch/etc/config.xml ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!--
3
+ * The MIT License (MIT)
4
+ *
5
+ * Copyright (c) 2016 FINDOLOGIC
6
+ *
7
+ * Permission is hereby granted, free of charge, to any person obtaining a
8
+ * copy of this software and associated documentation files (the "Software"),
9
+ * to deal in the Software without restriction, including without limitation
10
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11
+ * and/or sell copies of the Software, and to permit persons to whom
12
+ * the Software is furnished to do so, subject to the following conditions:
13
+ *
14
+ * The above copyright notice and this permission notice shall be included
15
+ * in all copies or substantial portions of the Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
18
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
19
+ * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
22
+ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+ -->
24
+ <config>
25
+ <modules>
26
+ <FINDOLOGIC_OnSiteSearch>
27
+ <version>1.0.4</version>
28
+ </FINDOLOGIC_OnSiteSearch>
29
+ </modules>
30
+
31
+ <global>
32
+ <helpers>
33
+ <findologic>
34
+ <class>FINDOLOGIC_OnSiteSearch_Helper</class>
35
+ </findologic>
36
+ </helpers>
37
+ <models>
38
+ <findologic>
39
+ <class>FINDOLOGIC_OnSiteSearch_Model</class>
40
+ </findologic>
41
+ </models>
42
+ </global>
43
+
44
+ <frontend>
45
+ <routers>
46
+ <findologic>
47
+ <use>standard</use>
48
+ <args>
49
+ <module>FINDOLOGIC_OnSiteSearch</module>
50
+ <frontName>findologic</frontName>
51
+ </args>
52
+ </findologic>
53
+ </routers>
54
+ <events>
55
+ <checkout_onepage_controller_success_action>
56
+ <observers>
57
+ <FINDOLOGIC_OnSiteSearch>
58
+ <type>singleton</type>
59
+ <class>FINDOLOGIC_OnSiteSearch_Model_Observer</class>
60
+ <method>onCheckoutOnepageControllerSuccess</method>
61
+ </FINDOLOGIC_OnSiteSearch>
62
+ </observers>
63
+ </checkout_onepage_controller_success_action>
64
+ </events>
65
+ <layout>
66
+ <updates>
67
+ <FINDOLOGIC_OnSiteSearch module="FINDOLOGIC_OnSiteSearch">
68
+ <file>findologic_onsitesearch.xml</file>
69
+ </FINDOLOGIC_OnSiteSearch>
70
+ </updates>
71
+ </layout>
72
+ </frontend>
73
+ </config>
app/code/community/FINDOLOGIC/OnSiteSearch/etc/system.xml ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!--
3
+ * The MIT License (MIT)
4
+ *
5
+ * Copyright (c) 2016 FINDOLOGIC
6
+ *
7
+ * Permission is hereby granted, free of charge, to any person obtaining a
8
+ * copy of this software and associated documentation files (the "Software"),
9
+ * to deal in the Software without restriction, including without limitation
10
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11
+ * and/or sell copies of the Software, and to permit persons to whom
12
+ * the Software is furnished to do so, subject to the following conditions:
13
+ *
14
+ * The above copyright notice and this permission notice shall be included
15
+ * in all copies or substantial portions of the Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
18
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
19
+ * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
22
+ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+ -->
24
+ <config>
25
+ <tabs>
26
+ <findologic translate="label">
27
+ <label>FINDOLOGIC</label>
28
+ <sort_order>100</sort_order>
29
+ </findologic>
30
+ </tabs>
31
+ <sections>
32
+ <findologic translate="label">
33
+ <label>Configuration</label>
34
+ <tab>findologic</tab>
35
+ <sort_order>100</sort_order>
36
+ <show_in_default>1</show_in_default>
37
+ <show_in_website>1</show_in_website>
38
+ <show_in_store>1</show_in_store>
39
+
40
+ <groups>
41
+ <findologic_group translate="label">
42
+ <label>Shop key options</label>
43
+ <frontend_type>text</frontend_type>
44
+ <sort_order>1</sort_order>
45
+ <show_in_default>1</show_in_default>
46
+ <show_in_website>1</show_in_website>
47
+ <show_in_store>1</show_in_store>
48
+
49
+ <fields>
50
+ <label translate="label">
51
+ <label>Use store view to insert shop key</label>
52
+ <frontend_type>label</frontend_type>
53
+ <show_in_default>1</show_in_default>
54
+ <show_in_website>1</show_in_website>
55
+ <show_in_store>0</show_in_store>
56
+ </label>
57
+ <shopkey translate="label">
58
+ <label>Shop Key</label>
59
+ <frontend_type>text</frontend_type>
60
+ <backend_model>findologic/shopkeyValidation</backend_model>
61
+ <show_in_default>0</show_in_default>
62
+ <show_in_website>0</show_in_website>
63
+ <show_in_store>1</show_in_store>
64
+ <comment>Insert shop key</comment>
65
+ </shopkey>
66
+ </fields>
67
+ </findologic_group>
68
+ </groups>
69
+ </findologic>
70
+ </sections>
71
+ </config>
app/design/frontend/base/default/layout/findologic_onsitesearch.xml ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!--
3
+ * The MIT License (MIT)
4
+ *
5
+ * Copyright (c) 2016 FINDOLOGIC
6
+ *
7
+ * Permission is hereby granted, free of charge, to any person obtaining a
8
+ * copy of this software and associated documentation files (the "Software"),
9
+ * to deal in the Software without restriction, including without limitation
10
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11
+ * and/or sell copies of the Software, and to permit persons to whom
12
+ * the Software is furnished to do so, subject to the following conditions:
13
+ *
14
+ * The above copyright notice and this permission notice shall be included
15
+ * in all copies or substantial portions of the Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
18
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
19
+ * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
22
+ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+ -->
24
+ <layout version="1.0.0">
25
+ <default>
26
+ <reference name="head">
27
+ <block type="core/template" name="findologic.search" template="findologic/head.phtml"/>
28
+ </reference>
29
+ </default>
30
+ </layout>
app/design/frontend/base/default/template/findologic/head.phtml ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * The MIT License (MIT)
4
+ *
5
+ * Copyright (c) 2016 FINDOLOGIC
6
+ *
7
+ * Permission is hereby granted, free of charge, to any person obtaining a
8
+ * copy of this software and associated documentation files (the "Software"),
9
+ * to deal in the Software without restriction, including without limitation
10
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11
+ * and/or sell copies of the Software, and to permit persons to whom
12
+ * the Software is furnished to do so, subject to the following conditions:
13
+ *
14
+ * The above copyright notice and this permission notice shall be included
15
+ * in all copies or substantial portions of the Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
18
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
19
+ * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
22
+ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+ *
24
+ * @category FINDOLOGIC
25
+ * @package FINDOLOGIC_OnSiteSearch
26
+ */
27
+ ?>
28
+ <?php
29
+ /** @var FINDOLOGIC_OnSiteSearch_Helper_TrackingScripts $tracking */
30
+ $tracking = Mage::helper('findologic/trackingScripts');
31
+ echo $tracking->renderScripts($this->getRequest());
32
+ ?>
app/etc/modules/FINDOLOGIC_OnSiteSearch.xml ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!--
3
+ * The MIT License (MIT)
4
+ *
5
+ * Copyright (c) 2016 FINDOLOGIC
6
+ *
7
+ * Permission is hereby granted, free of charge, to any person obtaining a
8
+ * copy of this software and associated documentation files (the "Software"),
9
+ * to deal in the Software without restriction, including without limitation
10
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11
+ * and/or sell copies of the Software, and to permit persons to whom
12
+ * the Software is furnished to do so, subject to the following conditions:
13
+ *
14
+ * The above copyright notice and this permission notice shall be included
15
+ * in all copies or substantial portions of the Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
18
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
19
+ * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
22
+ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+ -->
24
+ <config>
25
+ <modules>
26
+ <FINDOLOGIC_OnSiteSearch>
27
+ <active>true</active>
28
+ <codePool>community</codePool>
29
+ </FINDOLOGIC_OnSiteSearch>
30
+ </modules>
31
+ </config>
package.xml ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <package>
3
+ <name>FINDOLOGIC_OnSiteSearch</name>
4
+ <version>1.0.4</version>
5
+ <stability>stable</stability>
6
+ <license uri="https://opensource.org/licenses/MIT">MIT</license>
7
+ <channel>community</channel>
8
+ <extends/>
9
+ <summary>FINDOLOGIC is the ultimate search solution for your online store!</summary>
10
+ <description>FINDOLOGIC increases sales with a better search function in online store.</description>
11
+ <notes>Findologic Search module</notes>
12
+ <authors><author><name>FINDOLOGIC</name><user>FINDOLOGIC</user><email>support@findologic.com</email></author></authors>
13
+ <date>2016-08-30</date>
14
+ <time>09:54:14</time>
15
+ <contents><target name="magecommunity"><dir name="FINDOLOGIC"><dir name="OnSiteSearch"><dir name="Helper"><file name="TrackingScripts.php" hash="6afc96537e13bf75c70879858f727cc6"/><file name="Xml.php" hash="96e3c3c592aac7c4577a19ec66bb6662"/><file name="XmlBasic.php" hash="3d0e0cd8e7acc6ea3daefb8a8023c80d"/></dir><dir name="Model"><file name="Observer.php" hash="cf44ebef50dddd2f4f3a0cc27e55e2d5"/><file name="ShopkeyValidation.php" hash="fc06209c20b5443bfe933d687badb66b"/></dir><dir name="controllers"><file name="ExportController.php" hash="87223d81f2818a3f6fc88274c153812d"/></dir><dir name="etc"><file name="adminhtml.xml" hash="1b74a14bd7b6bb504734edbe6322e263"/><file name="config.xml" hash="1fc1e2e317685f0813d595d55860d551"/><file name="system.xml" hash="99c331d898e21037e0b9b3f352a308c1"/></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="FINDOLOGIC_OnSiteSearch.xml" hash="b3bdfd207ec2bc248629769b095d6745"/></dir></target><target name="magedesign"><dir name="frontend"><dir name="base"><dir name="default"><dir name="template"><dir name="findologic"><file name="head.phtml" hash="fe8b7f3f846099ca86ce94d567875200"/></dir></dir><dir name="layout"><file name="findologic_onsitesearch.xml" hash="5e6be64e166f6e1fdc62b1be27011249"/></dir></dir></dir></dir></target></contents>
16
+ <compatible/>
17
+ <dependencies><required><php><min>5.3.0</min><max>6.0.0</max></php></required></dependencies>
18
+ </package>