StrandsRecommender - Version 1.3.3

Version Notes

First release of the Strands Recommender plugin for the Magento community.

Visit http://recommender.strands.com/magento

Download this release

Release Info

Developer Magento Core Team
Extension StrandsRecommender
Version 1.3.3
Comparing to
See all releases


Version 1.3.3

app/code/community/Strands/Recommender/Block/Js.php ADDED
@@ -0,0 +1,31 @@
1
+ <?php
2
+
3
+ Class Strands_Recommender_Block_Js extends Mage_Core_Block_Text
4
+ {
5
+
6
+ protected function _toHtml()
7
+ {
8
+ $model = Mage::getModel('recommender/abstract');
9
+
10
+ if (!$model->isActive()) {
11
+ return '';
12
+ }
13
+
14
+ $protocol = Mage::app()->getStore()->isCurrentlySecure() ? 'https' : 'http';
15
+ $this->addText('
16
+ <script type="text/javascript" src="'.$protocol.'://bizsolutions.strands.com/sbsstatic/js/sbsLib-1.0.min.js"></script>');
17
+
18
+ $this->addText('
19
+ <script language="Javascript" type="text/javascript">
20
+ try {
21
+ SBS.Worker.go("'.$model->getApiId().'");
22
+ } catch(ex) { }
23
+ </script>');
24
+
25
+ return parent::_toHtml();
26
+ }
27
+
28
+ }
29
+
30
+
31
+ ?>
app/code/community/Strands/Recommender/Block/System/Config/Form/Field.php ADDED
@@ -0,0 +1,13 @@
1
+ <?php
2
+
3
+ Class Strands_Recommender_Block_System_Config_Form_Field extends Mage_Adminhtml_Block_System_Config_Form_Field
4
+ {
5
+ public function render(Varien_Data_Form_Element_Abstract $element)
6
+ {
7
+ if (Mage::getStoreConfig('recommender/settings/freedirectory_hidden')
8
+ || Mage::getModel('recommender/abstract')->isActive()) return '';
9
+ return parent::render($element);
10
+ }
11
+
12
+ }
13
+ ?>
app/code/community/Strands/Recommender/Block/Widget.php ADDED
@@ -0,0 +1,251 @@
1
+ <?php
2
+
3
+ Class Strands_Recommender_Block_Widget extends Mage_Core_Block_Template
4
+ {
5
+ protected $_checkout = null;
6
+ protected $_quote = null;
7
+ protected $_template = "strands/recommender/widget.phtml";
8
+ protected $helper = null;
9
+
10
+
11
+ public function _construct()
12
+ {
13
+ parent::_construct();
14
+ $this->helper = Mage::helper('recommender');
15
+ }
16
+
17
+
18
+ /**
19
+ * Function is set to blank to prevent the Block from Auto Rendering
20
+ */
21
+ protected function _toHtml()
22
+ {
23
+ $model = Mage::getModel('recommender/abstract');
24
+ if (!$model->isActive()) {
25
+ return '';
26
+ }
27
+
28
+ if (!$this->hasData('widget_name')) $this->setWidgetName($this->_getTemplate());
29
+ //if (!$this->hasData('widget_name')) $this->setWidgetName($this->helper->getCurrentPage());
30
+ if (!$this->hasData('item')) $this->setItem($this->getBasketItems());
31
+ if (!$this->hasData('strands_id')) $this->setStrandsId($model->getStrandsId());
32
+
33
+ return parent::_toHtml();
34
+ }
35
+
36
+
37
+ /**
38
+ * @return the Items in the Basket or Items Ordered
39
+ */
40
+ protected function getBasketItems()
41
+ {
42
+
43
+ if ($_product = Mage::registry('product')) {
44
+ return urlencode($_product->getId());
45
+ }
46
+ elseif ($this->helper->getCurrentPage() == "checkout_cart_index" || $this->helper->getCurrentPage() == "checkout_cart") {
47
+ $ret = array();
48
+
49
+
50
+ foreach ($this->getQuote()->getAllVisibleItems() as $item) {
51
+ $ret[] = urlencode($item->getProductId());
52
+ }
53
+
54
+ return implode("_._", $ret);
55
+ }
56
+ elseif ($this->helper->getCurrentPage() == "checkout_onepage_success"
57
+ || $this->helper->getCurrentPage() == "checkout_success"
58
+ || $this->helper->getCurrentPage() == "checkout_success_index") {
59
+
60
+ $orders = $this->getOrders();
61
+ $ret = array();
62
+
63
+ foreach ($orders as $order) {
64
+ $ret[] = urlencode($this->setCurrentOrder($order)->addOrderItems()); // CHECK
65
+ }
66
+
67
+ return implode("_._", $ret);
68
+ }
69
+
70
+ return '';
71
+ }
72
+
73
+
74
+ /**
75
+ * Method to add Items to the order
76
+ *
77
+ * @return string of array joined with _._
78
+ */
79
+ protected function addOrderItems()
80
+ {
81
+ $order = $this->getCurrentOrder();
82
+ if (!$order) {
83
+ return '';
84
+ }
85
+
86
+ if (!$order instanceof Mage_Sales_Model_Order) {
87
+ $order = Mage::getModel('sales/order')->load($order);
88
+ }
89
+
90
+ if (!$order) {
91
+ return '';
92
+ }
93
+
94
+
95
+ $ret = array();
96
+ foreach ($order->getAllItems() as $item) {
97
+ if ($item->getParentItemId()) {
98
+ continue;
99
+ }
100
+
101
+ $ret[] = $item->getProductId();
102
+ }
103
+
104
+ return implode("_._",$ret);
105
+ }
106
+
107
+ protected function getOrders()
108
+ {
109
+ $quote = $this->getCheckout()->getLastQuoteId();
110
+ if (!$quote) {
111
+ return '';
112
+ }
113
+
114
+ if ($quote instanceof Mage_Sales_Model_Quote) {
115
+ $quoteId = $quote->getId();
116
+ } else {
117
+ $quoteId = $quote;
118
+ }
119
+
120
+ if (!$quoteId) {
121
+ return '';
122
+ }
123
+
124
+ $orders = Mage::getResourceModel('sales/order_collection')
125
+ ->addAttributeToFilter('quote_id', $quoteId)
126
+ ->load();
127
+
128
+ return $orders;
129
+ }
130
+
131
+
132
+ /**
133
+ * Method borrowed from Mage_Catalog_Block_Product
134
+ *
135
+ * @return product or false
136
+ */
137
+ public function getProduct()
138
+ {
139
+ if (!$this->hasData('product')) {
140
+ $this->setData('product', Mage::registry('product'));
141
+ }
142
+ return $this->getData('product');
143
+ }
144
+
145
+
146
+ /**
147
+ * Get active quote
148
+ *
149
+ * @return Mage_Sales_Model_Quote
150
+ */
151
+ public function getQuote()
152
+ {
153
+ if (null === $this->_quote) {
154
+ $this->_quote = $this->getCheckout()->getQuote();
155
+ }
156
+ return $this->_quote;
157
+ }
158
+
159
+ /**
160
+ * From Mage_Checkout_Block_Cart_Abstract
161
+ * Get checkout session
162
+ *
163
+ * @return Mage_Checkout_Model_session
164
+ */
165
+ public function getCheckout()
166
+ {
167
+ if (null === $this->_checkout) {
168
+ $this->_checkout = Mage::getSingleton('checkout/session');
169
+ }
170
+ return $this->_checkout;
171
+ }
172
+
173
+
174
+ /**
175
+ * Function to get the default template code
176
+ *
177
+ * @return string of Template name
178
+ */
179
+ protected function _getTemplate()
180
+ {
181
+ switch($this->helper->getCurrentPage()) {
182
+ case "cms_index_index":
183
+ return "cms_index_index";
184
+ break;
185
+
186
+ case "catalog_product_view":
187
+ return "catalog_product_view";
188
+ break;
189
+
190
+ case "catalog_category_view":
191
+ return "catalog_category_view";
192
+ break;
193
+
194
+ case "checkout_cart_index":
195
+ return "checkout_cart_index";
196
+ break;
197
+
198
+ case "checkout_onepage_success":
199
+ return "checkout_onepage_success";
200
+ break;
201
+
202
+ case "checkout_multishipping_success":
203
+ return "checkout_multishipping_success";
204
+ break;
205
+
206
+ default:
207
+ return "cms_index_index";
208
+ break;
209
+ }
210
+ }
211
+
212
+ public function getDFilter()
213
+ {
214
+ if (!$this->hasData('d_filter')) {
215
+ switch ($this->helper->getCurrentPage()) {
216
+ case 'catalog_product_view':
217
+ if ($this->getCatProduct()) {
218
+ $categories = $this->getProduct()->getCategoryIds();
219
+
220
+ $html = '';
221
+ $i = 1;
222
+ if (count($categories)) {
223
+ foreach ($categories as $_cat) {
224
+ $html .= ($i < count($categories)) ? $_cat . "_._" : $_cat;
225
+ }
226
+ $i++;
227
+ } else $html = false;
228
+ } else $html = false;
229
+ break;
230
+
231
+ case 'catalog_category_view':
232
+ $_category = Mage::registry('current_category');
233
+ $html = 'ctgy_name:'.$_category->getId();
234
+ break;
235
+
236
+ default:
237
+ $html = false;
238
+ break;
239
+ }
240
+ $this->setData('d_filter', $html);
241
+
242
+
243
+
244
+ }
245
+ return $this->getData('d_filter');
246
+ }
247
+
248
+ }
249
+
250
+
251
+ ?>
app/code/community/Strands/Recommender/Helper/Abstract.php ADDED
@@ -0,0 +1,35 @@
1
+ <?php
2
+
3
+ Class Strands_Recommender_Helper_Abstract extends Varien_Object
4
+ {
5
+
6
+ /**
7
+ * Translate, borrowed from Mage_Core_Helper_Abstract
8
+ *
9
+ * @return string
10
+ */
11
+ public function __()
12
+ {
13
+ $args = func_get_args();
14
+ $expr = new Mage_Core_Model_Translate_Expr(array_shift($args), $this->_getModuleName());
15
+ array_unshift($args, $expr);
16
+ return Mage::app()->getTranslator()->translate($args);
17
+ }
18
+
19
+
20
+ /**
21
+ * Retrieve helper module name
22
+ *
23
+ * @return string
24
+ */
25
+ protected function _getModuleName()
26
+ {
27
+ if (!$this->_moduleName) {
28
+ $class = get_class($this);
29
+ $this->_moduleName = substr($class, 0, strpos($class, '_Helper'));
30
+ }
31
+ return $this->_moduleName;
32
+ }
33
+ }
34
+
35
+ ?>
app/code/community/Strands/Recommender/Helper/Data.php ADDED
@@ -0,0 +1,27 @@
1
+ <?php
2
+
3
+ Class Strands_Recommender_Helper_Data extends Strands_Recommender_Helper_Abstract
4
+ {
5
+
6
+
7
+ /**
8
+ * @return the current page
9
+ */
10
+ public function getCurrentPage()
11
+ {
12
+ if (!$this->hasData("current_page")) {
13
+ $module = strtolower(Mage::app()->getRequest()->getModuleName());
14
+ $controller = strtolower(Mage::app()->getRequest()->getControllerName());
15
+ $action = strtolower(Mage::app()->getRequest()->getActionName());
16
+
17
+ if (isset($action) && $action != '') $this->setCurrentPage($module.'_'.$controller.'_'.$action);
18
+ elseif (isset($controller) && $controller != '') $this->setCurrentPage($module.'_'.$controller.'_index');
19
+ else $this->setCurrentPage($module."_index_index");
20
+
21
+ if ($this->getCurrentPage() == 'checkout_multishipping_success') $this->setCurrentPage('checkout_onepage_success');
22
+ } return $this->getData('current_page');
23
+ }
24
+
25
+ }
26
+
27
+ ?>
app/code/community/Strands/Recommender/Helper/Logger.php ADDED
@@ -0,0 +1,48 @@
1
+ <?php
2
+
3
+ Class Strands_Recommender_Helper_Logger extends Strands_Recommender_Helper_Data
4
+ {
5
+ const PREFIX = "Strands ";
6
+ const ERROR1 = "Error: Insufficient permissions. File/directory is not writeable";
7
+
8
+ protected $_log = "recommender.log";
9
+ protected $_logHandler = null;
10
+
11
+
12
+ /**
13
+ * Method to log error messages
14
+ *
15
+ * @param $message is error message we are seeking to log
16
+ * @return boolean, true on success
17
+ */
18
+ public function log($message)
19
+ {
20
+ if ($this->_logHandler === null) {
21
+ $folder = Mage::getConfig()->getVarDir() . "/log";
22
+
23
+ if (!file_exists($folder)) {
24
+ if (!@mkdir($folder)) {
25
+ echo self::PREFIX . self::ERROR1 . "\r\n";
26
+ return false;
27
+ }
28
+ }
29
+
30
+ if (!$this->_logHandler = @fopen($folder . DS . $this->_log, 'a')) {
31
+ echo self::PREFIX . self::ERROR1 . "\r\n";
32
+ return false;
33
+ }
34
+
35
+
36
+ }
37
+
38
+ fwrite($this->_logHandler, self::PREFIX . " [" . date("mdY h:i:s") ."]: " . $message . "\r\n");
39
+ return true;
40
+ }
41
+
42
+ public function __destruct()
43
+ {
44
+ fclose($this->_logHandler);
45
+ }
46
+ }
47
+
48
+ ?>
app/code/community/Strands/Recommender/Model/Abstract.php ADDED
@@ -0,0 +1,339 @@
1
+ <?php
2
+
3
+ Class Strands_Recommender_Model_Abstract extends Mage_Core_Model_Abstract
4
+ {
5
+
6
+ public function getVersion()
7
+ {
8
+ $version = '1.3.2';
9
+ return $version;
10
+
11
+ }
12
+
13
+
14
+ /**
15
+ * Method to retrieve Strands Id Stored in Cookie
16
+ *
17
+ * @return self with data
18
+ */
19
+ public function getStrandsId($logged = false)
20
+ {
21
+ if (!$this->hasData('strands_id')) {
22
+ $session = Mage::getSingleton("customer/session");
23
+
24
+ if ($session->isLoggedIn()) {
25
+ $this->setStrandsId($session->getCustomerId());
26
+ Mage::getModel('core/cookie')->set('strandsSBS_P_UserId',$session->getCustomerId(),true,'/',null,null,false);
27
+ } elseif ($logged) {
28
+ if (strlen(Mage::app()->getFrontController()->getRequest()->getCookie('strandsSBS_P_UserId')))
29
+ return Mage::app()->getFrontController()->getRequest()->getCookie('strandsSBS_P_UserId');
30
+ elseif (strlen(Mage::app()->getFrontController()->getRequest()->getCookie('strandsSBS_S_UserId')))
31
+ return Mage::app()->getFrontController()->getRequest()->getCookie('strandsSBS_S_UserId');
32
+ else {
33
+ $newCookie = $this->create_anon_cookie();
34
+ Mage::getModel('core/cookie')->set('strandsSBS_S_UserId',$newCookie,true,'/',null,null,false);
35
+ return $newCookie;
36
+ }
37
+ } else {
38
+ $this->setStrandsId('');
39
+ }
40
+ }
41
+ return $this->getData('strands_id');
42
+
43
+ }
44
+
45
+ /**
46
+ * Method to create an anonymous cookie
47
+ */
48
+ private function create_anon_cookie()
49
+ {
50
+
51
+ //$cookie = 'MGN_'.rand(0,1000).(((int)(time()/1000))*rand(0,1000)).rand(0,1000).'_'.$this->ms_time();
52
+ $cookie = 'MGN_'.$this->ms_time().'_'.rand(0,100000);
53
+ return $cookie;
54
+ }
55
+
56
+ private function ms_time()
57
+ {
58
+ $timeday = gettimeofday();
59
+ $sec = intval($timeday['sec']);
60
+ $msec = intval(floor($timeday['usec']/1000));
61
+ if (strlen($msec) == 2) $msec = '0'.$msec;
62
+ elseif (strlen($msec) == 1) $msec = '00'.$msec;
63
+
64
+ return $sec.$msec;
65
+ }
66
+
67
+ /**
68
+ * Method to check if the module is active
69
+ *
70
+ * @return bool
71
+ */
72
+ public function isActive()
73
+ {
74
+ if (!Mage::getStoreConfigFlag('recommender/settings/active')) return false;
75
+ //if (strlen($this->getCustomerId()) < 1) return false;
76
+ if (strlen($this->getApiId()) < 1) return false;
77
+ if (strlen($this->getCustomerToken()) < 1) return false;
78
+ return true;
79
+ }
80
+
81
+ /**
82
+ * Method to check if the catalog must be uploaded in that very moment
83
+ *
84
+ * @return bool
85
+ */
86
+ public function getUploadCatalogNow()
87
+ {
88
+ if (!$this->hasData('recommender_uploadcatalognow')) {
89
+ $this->setData('recommender_uploadcatalognow', Mage::getStoreConfig('recommender/settings/strands_uploadcatalognow'));
90
+ }
91
+ return $this->getData('recommender_uploadcatalognow');
92
+ }
93
+
94
+ public function isDirectory()
95
+ {
96
+ if (!$this->isActive()) return false;
97
+ return (Mage::getStoreConfigFlag('recommender/settings/freedirectory')) ? true : false;
98
+ }
99
+
100
+ /**
101
+ * Method to retrieve customer id
102
+ *
103
+ * @return self
104
+ */
105
+
106
+ public function getCustomerId()
107
+ {
108
+ if (!$this->hasData('recommender_id')) {
109
+ $this->setData('recommender_id', Mage::getStoreConfig('recommender/settings/strands_customer_id'));
110
+ }
111
+ return $this->getData('recommender_id');
112
+ }
113
+
114
+
115
+
116
+ /**
117
+ * Method to retrieve api id
118
+ *
119
+ * @return self
120
+ */
121
+ public function getApiId()
122
+ {
123
+ if (!$this->hasData('recommender_api_id')) {
124
+ $this->setData('recommender_api_id', Mage::getStoreConfig('recommender/settings/strands_api_id'));
125
+ }
126
+ return $this->getData('recommender_api_id');
127
+ }
128
+
129
+
130
+ /**
131
+ * Method to retrieve customer token
132
+ *
133
+ * @return self
134
+ */
135
+ public function getCustomerToken()
136
+ {
137
+ if (!$this->hasData('recommender_customer_token')) {
138
+ $this->setData('recommender_customer_token', Mage::getStoreConfig('recommender/settings/strands_customer_token'));
139
+ }
140
+ return $this->getData('recommender_customer_token');
141
+ }
142
+
143
+
144
+ /**
145
+ * Method to retrieve strands login
146
+ *
147
+ * @return self
148
+ */
149
+ public function getLogin()
150
+ {
151
+ if (!$this->hasData('recommender_login')) {
152
+ $this->setData('recommender_login', Mage::getStoreConfig('recommender/settings/strands_login'));
153
+ }
154
+ return $this->getData('recommender_login');
155
+ }
156
+
157
+
158
+ /**
159
+ * Method to retrieve strands password
160
+ *
161
+ * @return self
162
+ */
163
+ public function getPassword()
164
+ {
165
+ if (!$this->hasData('recommender_pass')) {
166
+ $this->setData('recommender_pass', Mage::getStoreConfig('recommender/settings/strands_password'));
167
+ }
168
+ return $this->getData('recommender_pass');
169
+ }
170
+
171
+
172
+ /**
173
+ * Method to retrieve desired catalog upload time
174
+ */
175
+ public function getDesiredCatalogTime()
176
+ {
177
+ if (!$this->hasData('recommender_desired_catalog_time')) {
178
+ $this->setData('recommender_desired_catalog_time', Mage::getStoreConfig('recommender/settings/strands_desired_catalog_time'));
179
+ }
180
+ return $this->getData('recommender_desired_catalog_time');
181
+ }
182
+
183
+ /**
184
+ * Method to retrieve Log status
185
+ *
186
+ * @return self with data
187
+ */
188
+ public function getLogStatus()
189
+ {
190
+ if (!$this->hasData('log_status')) {
191
+ $this->setData('log_status', Mage::getStoreConfig('recommender/settings/log'));
192
+ }
193
+ return $this->getData('log_status');
194
+ }
195
+
196
+ /**
197
+ * Method borrowed from Mage_Catalog_Block_Product
198
+ *
199
+ * @return product or false
200
+ */
201
+ public function getCurrentProduct()
202
+ {
203
+ if (!$this->hasData('product')) {
204
+ $this->setData('product', Mage::registry('product'));
205
+ }
206
+ return $this->getData('product');
207
+ }
208
+
209
+
210
+ public function extractCatalog($localpath,$localfile)
211
+ {
212
+
213
+ $xml = new DOMDocument('1.0','utf-8');
214
+ $store = Mage::app()->getStore();
215
+
216
+ $model = Mage::getModel('recommender/abstract');
217
+
218
+ $root = $xml->createElement('sbs-catalog');
219
+ $root->appendChild($xml->createAttribute('version'))->appendChild($xml->createTextNode('1.0'));
220
+ $xml->appendChild($root);
221
+
222
+ $root->appendChild($xml->createElement('company'))->appendChild($xml->createTextNode(htmlentities(Mage::getStoreConfig('general/store_information/name'))));
223
+ $root->appendChild($xml->createElement('link'))->appendChild($xml->createTextNode(htmlentities($store->getBaseUrl())));
224
+ $root->appendChild($xml->createElement('description'))->appendChild($xml->createTextNode(htmlentities(Mage::getStoreConfig('general/store_information/name'))));
225
+
226
+ $collection = Mage::getModel('catalog/product')
227
+ ->getCollection()
228
+ ->addAttributeToSelect('sku')
229
+ ->addAttributeToSelect('name')
230
+ ->addAttributeToSelect('attribute_set_id')
231
+ ->addAttributeToSelect('type_id');
232
+
233
+ foreach ($collection as $item) {
234
+ $_product = Mage::getModel('catalog/product')->load($item->getId());
235
+
236
+ $parentIdArray = $_product->loadParentProductIds()->getData('parent_product_ids');
237
+ if (count($parentIdArray) && $_product->getVisibility() == 1) {
238
+ continue;
239
+ }
240
+
241
+ $item = $xml->createElement('item');
242
+ $item->appendChild($xml->createElement('id'))->appendChild($xml->createCDATASection($_product->getId()));
243
+ $item->appendChild($xml->createElement('title'))->appendChild($xml->createCDATASection("'".htmlentities($_product->getName()."'")));
244
+ $item->appendChild($xml->createElement('link'))->appendChild($xml->createTextNode(htmlentities($_product->getProductUrl())));
245
+ $item->appendChild($xml->createElement('description'))->appendChild($xml->createCDATASection($_product->getDescription()));
246
+ $item->appendChild($xml->createElement('image_link'))->appendChild($xml->createTextNode(htmlentities(Mage::helper('catalog/image')->init($_product,'image'))));
247
+ $item->appendChild($xml->createElement('small_image_link'))->appendChild($xml->createTextNode(htmlentities(Mage::helper('catalog/image')->init($_product,'small_image')->resize(135))));
248
+ $item->appendChild($xml->createElement('saleprice'))->appendChild($xml->createCDATASection($_product->getPrice()));
249
+
250
+ $item->appendChild($xml->createElement('sku'))->appendChild($xml->createCDATASection($_product->getSku()));
251
+
252
+ $_attributes = $this->getAdditionalData($_product);
253
+
254
+ foreach ($_attributes as $_attr) {
255
+ $item->appendChild($xml->createElement('a_'.$_attr['code']))->appendChild($xml->createCDATASection($_attr['value']));
256
+ }
257
+
258
+
259
+
260
+ $_options = $_product->getOptions();
261
+ if (count($_options)) {
262
+ foreach($_options as $_option) {
263
+ foreach ($_option->getData() as $_key => $_val) {
264
+ $item->appendChild($xml->createElement('o_'.$_key))->appendChild($xml->createCDATASection($_val));
265
+ }
266
+
267
+ foreach($_option->getValues() as $_value) {
268
+ foreach ($_value->getData() as $_key => $_val) {
269
+ $item->appendChild($xml->createElement('o_'.$_key))->appendChild($xml->createCDATASection($_val));
270
+ }
271
+ }
272
+ }
273
+ }
274
+
275
+ if (count($_product->getCategoryIds())) {
276
+ foreach ($_product->getCategoryIds() as $_cat) {
277
+ $item->appendChild($xml->createElement('category'))->appendChild($xml->createTextNode($_cat));
278
+ }
279
+ }
280
+
281
+ $root->appendChild($item);
282
+
283
+ }
284
+
285
+ $output = $xml->saveXML();
286
+
287
+ $sc = fopen("$localpath$localfile",'w');
288
+ fwrite($sc,$output);
289
+ fclose($sc);
290
+
291
+ }
292
+
293
+
294
+
295
+ /**
296
+ * Code borrowed from Mage_Catalog_Block_Product_View_Attributes
297
+ *
298
+ * @return additional data for product
299
+ */
300
+ public function getAdditionalData($product, array $excludeAttr = array())
301
+ {
302
+ if (!$product) return;
303
+
304
+ $data = array();
305
+ //$product = $product;
306
+ $attributes = $product->getAttributes();
307
+ foreach ($attributes as $attribute) {
308
+ // if ($attribute->getIsVisibleOnFront() && $attribute->getIsUserDefined() && !in_array($attribute->getAttributeCode(), $excludeAttr)) {
309
+ if (!in_array($attribute->getAttributeCode(), $excludeAttr)) {
310
+
311
+ $value = $attribute->getFrontend()->getValue($product);
312
+
313
+ // TODO this is temporary skipping eco taxes
314
+ if (is_string($value)) {
315
+ if (strlen($value) && $product->hasData($attribute->getAttributeCode())) {
316
+ if ($attribute->getFrontendInput() == 'price') {
317
+ $value = Mage::app()->getStore()->convertPrice($value,true);
318
+ }
319
+
320
+ //$value = htmlentities($value); // REMOVED
321
+ $data[$attribute->getAttributeCode()] = array(
322
+ 'label' => $attribute->getStoreLabel(),
323
+ 'value' => $value,
324
+ 'code' => $attribute->getAttributeCode()
325
+ );
326
+ }
327
+ }
328
+ }
329
+ }
330
+ return $data;
331
+ }
332
+
333
+
334
+
335
+
336
+
337
+ }
338
+
339
+ ?>
app/code/community/Strands/Recommender/Model/Api.php ADDED
@@ -0,0 +1,194 @@
1
+ <?php
2
+
3
+ Class Strands_Recommender_Model_Api extends Strands_Recommender_Model_Abstract
4
+ {
5
+ const DEBUG = false;
6
+
7
+ protected $_items = null;
8
+ protected $_param = array();
9
+
10
+
11
+ public function _construct()
12
+ {
13
+ $this->setBaseApiUrl("http://bizsolutions.strands.com/api2/event/");
14
+ }
15
+
16
+
17
+ /**
18
+ * Method for Api Call
19
+ *
20
+ * @param $args array of different args for the call
21
+ */
22
+ public function callApi()
23
+ {
24
+ $session = Mage::getSingleton('core/session');
25
+
26
+ //if (!$this->isActive()) return;
27
+
28
+ ///$apiCall = $this->getBaseApiUrl() . $this->getApiAction() . '.sbs?apid=' . $this->getApiId();
29
+
30
+ $apiCall = $this->getBaseApiUrl();
31
+
32
+ if ($this->getApiAction()) {
33
+ $apiCall = $apiCall . $this->getApiAction() . '.sbs?apid=' . $this->getApiId();
34
+ } else {
35
+ $apiCall = $apiCall . '?apid=' . $this->getApiId() . '&token=' . $this->getCustomerToken();
36
+ $apiCall = $apiCall . '&version=' . $this->getVersion();
37
+ if ($this->getTarget() == 'setup') {
38
+ $apiCall = $apiCall . '&id=id&title=title&link=link&description=description&image_link=image_link&price=saleprice&tag=tag&category=category';
39
+ }
40
+ }
41
+
42
+
43
+ if ($this->getApiAction() == 'userlogged'){
44
+ /*
45
+ * Block for user logged in action
46
+ */
47
+ $apiCall .= "&olduser=" . $this->getOldUser();
48
+ }
49
+ elseif ($this->getApiAction() == "addshoppingcart") {
50
+ /*
51
+ * Block for modifying the shopping cart
52
+ */
53
+
54
+ if (count($this->getCartItems())) {
55
+ $_items = '';
56
+
57
+ foreach ($this->getCartItems() as $item) {
58
+ if ($item->getHasChildren()) {
59
+ if ($item->getParentItem() != null) {
60
+ continue;
61
+ } else {
62
+ continue;
63
+ }
64
+ } else {
65
+ if ($item->getParentItem() != null) {
66
+ $_items .= "&item=" . urlencode($item->getParentItem()->getProductId());
67
+ } else {
68
+ $_items .= "&item=" . urlencode($item->getProductId());
69
+ }
70
+ }
71
+ }
72
+ $apiCall .= $_items;
73
+ }
74
+ }
75
+
76
+ if ($this->hasData('product')) $apiCall .= "&item=" . urlencode($this->getProduct());
77
+ if ($this->hasData('items')) $apiCall .= $this->getItems();
78
+ if ($this->hasData('search_keywords')) $apiCall .= "&searchstring=" . urlencode($this->getSearchKeywords());
79
+ if ($this->hasData('user') && strlen($this->getUser())) $apiCall .= "&user=" . $this->getUser();
80
+ if ($this->hasData('type')) $apiCall .= "&type=" . $this->getType();
81
+ if ($this->hasData('passv_api_url')) $apiCall .= "&passvapi=" . $this->getPassvApiUrl();
82
+ if ($this->hasData('currency')) $apiCall .= "&currency=" . $this->getCurrency();
83
+
84
+ $response = $this->makeCall($apiCall);
85
+
86
+
87
+ if ($this->getLogStatus()) {
88
+ $message = ($response['success']) ? 'Success' : 'Failed';
89
+ $message .= ": Request Call: $apiCall\r\n";
90
+ $message .= $response['message'];
91
+
92
+
93
+ if (!$success = Mage::helper('recommender/logger')->log($message)) {
94
+ //$session->addError('Recommender log failed to instantate or write');
95
+ }
96
+ }
97
+
98
+ //if ($response['success']) $session->addError($response['message']);
99
+ //else $session->addError($response['message']);
100
+
101
+ return $this;
102
+ }
103
+
104
+
105
+ /**
106
+ * Method for cURL call
107
+ *
108
+ * @param $url is the URL we are calling
109
+ * @return array response
110
+ */
111
+ protected function makeCall($url, $params = array())
112
+ {
113
+ $ret = array('success' => true);
114
+
115
+ try {
116
+ $curl = curl_init();
117
+ curl_setopt($curl, CURLOPT_URL, $url);
118
+ curl_setopt($curl, CURLOPT_FOLLOWLOCATION, false);
119
+ curl_setopt($curl, CURLOPT_HEADER, false);
120
+ curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); //
121
+ //curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 2);
122
+ curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
123
+ curl_setopt($curl, CURLOPT_USERAGENT, "Magento Strands Recommender v1.0");
124
+
125
+ if (isset($params['CURLOPT']) && count($params['CURLOPT'])) {
126
+ foreach ($params['CURLOPT'] as $k => $v) {
127
+ curl_setopt($curl, constant("CURLOPT_$k"), $v);
128
+ }
129
+ }
130
+
131
+ $ret['message'] = curl_exec($curl);
132
+ $ret['message'] = ($this->getMessage()) ? $ret['message'] : 'Success';
133
+
134
+ curl_close($curl);
135
+ } catch(Exception $e) {
136
+ $ret['success'] = false;
137
+ $ret['message'] = $e->getMessage();
138
+ }
139
+
140
+ return $ret;
141
+ }
142
+
143
+ public function callApiTwo()
144
+ {
145
+ $apiCall = $this->getBaseApiUrl() . "?";
146
+ $session = Mage::getModel('adminhtml/session');
147
+
148
+ $i = 0;
149
+ $params_data = '';
150
+ foreach ($this->_param as $key => $val) {
151
+ $params_data .= ($i > 0) ? "&$key=$val" : "$key=$val";
152
+ $i++;
153
+ }
154
+
155
+ $options = array(
156
+ 'CURLOPT' => array(
157
+ 'POST' => true,
158
+ 'POSTFIELDS' => $params_data
159
+ ));
160
+
161
+ $response = $this->makeCall($apiCall, $options);
162
+
163
+ $serialOpts = serialize($options);
164
+ if ($this->getLogStatus()) {
165
+ $message = ($response['success']) ? 'Success' : 'Failed';
166
+ $message .= ": Request Call: $apiCall\r\n";
167
+ $message .= "Params: $params_data\r\n";
168
+ $message .= "Options: $options\r\n";
169
+ $message .= $response['message'];
170
+
171
+
172
+ if (!$success = Mage::helper('recommender/logger')->log($message)) {
173
+ //$session->addError('Recommender log failed to instantate or write');
174
+ }
175
+ }
176
+
177
+ return $this;
178
+ }
179
+
180
+ public function setParam($key, $val)
181
+ {
182
+ $this->_param[$key] = $val;
183
+ return $this;
184
+ }
185
+
186
+ protected function getMessage()
187
+ {
188
+ if (!$this->hasData('message')) $this->setMessage(true);
189
+ return $this->getData('message');
190
+ }
191
+
192
+ }
193
+
194
+ ?>
app/code/community/Strands/Recommender/Model/Numberoption.php ADDED
@@ -0,0 +1,48 @@
1
+ <?php
2
+
3
+
4
+ /**
5
+ * Used in creating options for Numbers selection
6
+ *
7
+ */
8
+ class Strands_Recommender_Model_Numberoption
9
+ {
10
+
11
+ /**
12
+ * Options getter
13
+ *
14
+ * @return array
15
+ */
16
+ public function toOptionArray()
17
+ {
18
+ return array(
19
+ array('value' => 0, 'label'=>Mage::helper('adminhtml')->__('0')),
20
+ array('value' => 1, 'label'=>Mage::helper('adminhtml')->__('1')),
21
+ array('value' => 2, 'label'=>Mage::helper('adminhtml')->__('2')),
22
+ array('value' => 3, 'label'=>Mage::helper('adminhtml')->__('3')),
23
+ array('value' => 4, 'label'=>Mage::helper('adminhtml')->__('4')),
24
+ array('value' => 5, 'label'=>Mage::helper('adminhtml')->__('5')),
25
+ array('value' => 6, 'label'=>Mage::helper('adminhtml')->__('6')),
26
+ array('value' => 7, 'label'=>Mage::helper('adminhtml')->__('7')),
27
+ array('value' => 8, 'label'=>Mage::helper('adminhtml')->__('8')),
28
+ array('value' => 9, 'label'=>Mage::helper('adminhtml')->__('9')),
29
+ array('value' => 10, 'label'=>Mage::helper('adminhtml')->__('10')),
30
+ array('value' => 11, 'label'=>Mage::helper('adminhtml')->__('11')),
31
+ array('value' => 12, 'label'=>Mage::helper('adminhtml')->__('12')),
32
+ array('value' => 13, 'label'=>Mage::helper('adminhtml')->__('13')),
33
+ array('value' => 14, 'label'=>Mage::helper('adminhtml')->__('14')),
34
+ array('value' => 15, 'label'=>Mage::helper('adminhtml')->__('15')),
35
+ array('value' => 16, 'label'=>Mage::helper('adminhtml')->__('16')),
36
+ array('value' => 17, 'label'=>Mage::helper('adminhtml')->__('17')),
37
+ array('value' => 18, 'label'=>Mage::helper('adminhtml')->__('18')),
38
+ array('value' => 19, 'label'=>Mage::helper('adminhtml')->__('19')),
39
+ array('value' => 20, 'label'=>Mage::helper('adminhtml')->__('20')),
40
+ array('value' => 21, 'label'=>Mage::helper('adminhtml')->__('21')),
41
+ array('value' => 22, 'label'=>Mage::helper('adminhtml')->__('22')),
42
+ array('value' => 23, 'label'=>Mage::helper('adminhtml')->__('23')),
43
+ );
44
+ }
45
+
46
+ }
47
+
48
+ ?>
app/code/community/Strands/Recommender/Model/Observer.php ADDED
@@ -0,0 +1,297 @@
1
+ <?php
2
+
3
+ Class Strands_Recommender_Model_Observer extends Strands_Recommender_Model_Abstract
4
+ {
5
+
6
+
7
+ /**
8
+ * replacement constructor method
9
+ */
10
+ protected function _construct()
11
+ {
12
+ parent::_construct();
13
+ }
14
+
15
+
16
+ /**
17
+ * call method for events
18
+ * At call we make a url call to strands
19
+ *
20
+ * @param $observer observer from the dispatch Event
21
+ */
22
+ public function eventCartChange($observer)
23
+ {
24
+ if (!$this->isActive()) return;
25
+ $api = Mage::getSingleton('recommender/api');
26
+
27
+ $api->setApiAction('addshoppingcart')
28
+ ->setUser($this->getStrandsId(true))
29
+ ->setCartItems($this->getCartItems())
30
+ ->callApi();
31
+
32
+ return $this;
33
+ }
34
+
35
+
36
+ public function eventWishlistAdd($observer)
37
+ {
38
+ if (!$this->isActive()) return;
39
+ $api = Mage::getSingleton('recommender/api');
40
+ $product = $observer->getEvent()->getProduct();
41
+
42
+ $api->setApiAction('addwishlist')
43
+ ->setUser($this->getStrandsId(true))
44
+ ->setProduct($product->getId())
45
+ ->callApi();
46
+
47
+ return $this;
48
+ }
49
+
50
+
51
+ public function eventUserLogin($observer)
52
+ {
53
+ if (!$this->isActive()) return;
54
+ $api = Mage::getSingleton('recommender/api');
55
+ $session = Mage::getSingleton("customer/session");
56
+
57
+ if (strlen(Mage::app()->getFrontController()->getRequest()->getCookie('strandsSBS_P_UserId'))) {
58
+ Mage::getModel('core/cookie')->set('strandsSBS_P_UserId',$session->getCustomerId(),true,'/',null,null,false);
59
+ } else {
60
+ if (strlen(Mage::app()->getFrontController()->getRequest()->getCookie('strandsSBS_S_UserId'))) {
61
+ $api->setApiAction('userlogged')
62
+ ->setOldUser(Mage::app()->getFrontController()->getRequest()->getCookie('strandsSBS_S_UserId'))
63
+ ->setUser($this->getStrandsId(true))
64
+ ->callApi();
65
+ } else {
66
+ Mage::getModel('core/cookie')->set('strandsSBS_P_UserId',$session->getCustomerId(),true,'/',null,null,false);
67
+ }
68
+ }
69
+
70
+ return $this;
71
+ }
72
+
73
+
74
+ public function eventPostDispatchSearch($observer)
75
+ {
76
+ if (!$this->isActive()) return;
77
+ $api = Mage::getSingleton('recommender/api');
78
+ $data = Mage::helper('recommender');
79
+
80
+ $api->setApiAction('searched')
81
+ ->setSearchKeywords(Mage::app()->getFrontController()->getRequest()->getParam('q'))
82
+ ->setUser($this->getStrandsId(true))
83
+ ->callApi();
84
+
85
+ return $this;
86
+ }
87
+
88
+
89
+ public function eventPostDispatchProductView($observer)
90
+ {
91
+ if (!$this->isActive()) return;
92
+
93
+ $api = Mage::getSingleton('recommender/api');
94
+ $data = Mage::helper('recommender');
95
+
96
+ $api->setApiAction('visited')
97
+ ->setProduct($this->getCurrentProduct()->getId())
98
+ ->setUser($this->getStrandsId(true))
99
+ ->callApi();
100
+
101
+ return $this;
102
+ }
103
+
104
+
105
+ public function eventPreDispatch($observer)
106
+ {
107
+ $api = Mage::getSingleton('recommender/api');
108
+ $data = Mage::helper('recommender');
109
+
110
+ $cont = $observer->getEvent()->getControllerAction();
111
+ $groups = $cont->getRequest()->getPost('groups');
112
+
113
+ if ($cont->getRequest()->getParam('section') == 'recommender') {
114
+ $callApi = false;
115
+ $freedirectory = false;
116
+
117
+ $fields = $cont->getRequest()->getParam('section');
118
+ if (intval(Mage::getStoreConfigFlag('recommender/settings/active')) != intval($groups['settings']['fields']['active']['value'])) {
119
+ if ($groups['settings']['fields']['active']['value']) {
120
+ //$api->setBaseApiUrl('https://recommender.strands.com/signup_activate');
121
+ $api->setBaseApiUrl('https://recommender.strands.com/account/plugin/setup/');
122
+ $api->setTarget('setup');
123
+ $callApi = true;
124
+ ///if ($groups['settings']['fields']['freedirectory']['value']) $freedirectory = true;
125
+ } else {
126
+ //$api->setBaseApiUrl('https://recommender.strands.com/signup_deactivate');
127
+ $api->setBaseApiUrl('https://recommender.strands.com/account/plugin/deactivate/');
128
+ $api->setTarget('deactivate');
129
+ $callApi = true;
130
+ }
131
+ }
132
+
133
+ elseif (Mage::getStoreConfig('recommender/settings/strands_api_id') != $groups['settings']['fields']['strands_api_id']['value']) {
134
+ //$api->setBaseApiUrl('https://recommender.strands.com/signup_activate');
135
+ $api->setBaseApiUrl('https://recommender.strands.com/account/plugin/setup/');
136
+ $api->setTarget('setup');
137
+ $callApi = true;
138
+ ///if ($groups['settings']['fields']['freedirectory']['value']) $freedirectory = true;
139
+ }
140
+
141
+ elseif (Mage::getStoreConfig('recommender/settings/strands_customer_token') != $groups['settings']['fields']['strands_customer_token']['value']) {
142
+ $api->setBaseApiUrl('https://recommender.strands.com/account/plugin/setup/');
143
+ $api->setTarget('setup');
144
+ $callApi = true;
145
+ }
146
+
147
+
148
+
149
+ if ($callApi)
150
+ $api->setType('magento')
151
+ ->setMessage(false)
152
+ ->setRecommenderApiId($groups['settings']['fields']['strands_api_id']['value'])
153
+ ->setRecommenderCustomerToken($groups['settings']['fields']['strands_customer_token']['value'])
154
+ ////->setPassvApiUrl(htmlentities(Mage::getUrl("recommender/index", array('_secure' => true))))
155
+ //->setPassvApiUrl('1')
156
+ ->callApi();
157
+
158
+
159
+ if ($freedirectory)
160
+ $api->setBaseApiUrl('http://www.emediastores.com/mcms/index.php')
161
+ ->setMessage(true)
162
+ ->setParam('rt', 'api/registerrv')
163
+ ->setParam('cart', 'magento')
164
+ ->setParam('passvapi', Mage::getUrl("recommender/index", array('_secure' => true)))
165
+ ->setParam('api', 'strands')
166
+ ->setParam('customer_id', $this->getCustomerId())
167
+ ->setParam('api_key', $this->getApiId())
168
+ ->setParam('store_code', Mage::app()->getStore()->getId())
169
+ ->setParam('store_name', Mage::app()->getStore()->getName())
170
+ ->setParam('store_owner', Mage::getStoreConfig('trans_email/ident_general/name'))
171
+ ->setParam('store_email', Mage::getStoreConfig('trans_email/ident_general/email'))
172
+ ->setParam('store_company', Mage::getStoreConfig('general/store_information/name'))
173
+ ->setParam('store_address', Mage::getStoreConfig('general/store_information/address'))
174
+ ->setParam('store_phone', Mage::getStoreConfig('general/store_information/phone'))
175
+ ->callApiTwo();
176
+
177
+
178
+ if (intval($groups['settings']['fields']['strands_catalog_upload_now']['value']) == 1) {
179
+ Mage::getConfig()->saveConfig('recommender/settings/strands_uploadcatalognow',time());
180
+ }
181
+
182
+ }
183
+
184
+
185
+ return $this;
186
+ }
187
+
188
+
189
+ public function eventPayInvoice($observer)
190
+ {
191
+ if (!$this->isActive()) return;
192
+ $api = Mage::getSingleton('recommender/api');
193
+ $order = $observer->getEvent()->getPayment()->getOrder();
194
+ $items = $order->getItemsCollection();
195
+
196
+ $itemsUrl = '';
197
+
198
+ foreach ($items as $item) {
199
+ if ($item->getHasChildren()) {
200
+ if ($item->getParentItem() != null) {
201
+ continue;
202
+ } else {
203
+ continue;
204
+ }
205
+ } else {
206
+ if ($item->getParentItem() != null) {
207
+ $itemsUrl .= "&item=" . urlencode($item->getParentItem()->getProductId() . "::" . $item->getParentItem()->getPrice() . "::" . $item->getParentItem()->getQtyOrdered());
208
+ } else {
209
+ $itemsUrl .= "&item=" . urlencode($item->getProductId() . "::" . $item->getPrice() . "::" . $item->getQtyOrdered());
210
+ }
211
+ }
212
+
213
+ }
214
+
215
+ if ($order->getOrderCurrencyCode() != null)
216
+ $currency_code = $order->getOrderCurrencyCode();
217
+ else
218
+ $currency_code = Mage::app()->getStore()->getCurrentCurrencyCode();
219
+
220
+ $api->setApiAction('purchased')
221
+ ->setUser($this->getStrandsId(true))
222
+ ->setItems($itemsUrl)
223
+ ->setCurrency($currency_code)
224
+ ->callApi();
225
+ }
226
+
227
+
228
+ public function uploadCatalog()
229
+ {
230
+
231
+ if (!$this->isActive()) return;
232
+
233
+ $timeBefore = date(DATE_RSS);
234
+
235
+ $timeCatalog = $this->getDesiredCatalogTime();
236
+ if ($timeCatalog == null)
237
+ $timeCatalog = '0';
238
+
239
+ $currentTime = getdate();
240
+ $currentHour = $currentTime['hours'];
241
+ $currentMinute = $currentTime['minutes'];
242
+ $catalogHour = intval($timeCatalog);
243
+
244
+ if (($this->getUploadCatalogNow()+65 < time()) && (($currentHour != $catalogHour) || ($currentMinute != intval('27')))) {
245
+ return;
246
+ }
247
+
248
+ $localfile = "strandsCatalog.xml";
249
+ $absPath = Mage::getBaseDir();
250
+ $localpath = $absPath."/media/";
251
+
252
+ $this->extractCatalog($localpath,$localfile);
253
+
254
+ $timeAfter = date(DATE_RSS);
255
+
256
+ $ftpserver = "recommender.strands.com";
257
+ $ftppath = "/catalog/complete";
258
+ $ftpuser = $this->getLogin();
259
+ $ftppass = $this->getPassword();
260
+
261
+ $remoteurl = "ftp://${ftpuser}:${ftppass}@${ftpserver}${ftppath}/${localfile}";
262
+
263
+ $fp = curl_init();
264
+
265
+ $lc = fopen("$localpath$localfile","r");
266
+
267
+ curl_setopt($fp, CURLOPT_URL, $remoteurl);
268
+ // curl_setopt($fp, CURLOPT_BINARYTRANSFER, 0);
269
+ curl_setopt($fp, CURLOPT_UPLOAD, 1);
270
+ curl_setopt($fp, CURLOPT_INFILE, $lc);
271
+
272
+ $success = curl_exec($fp);
273
+ curl_close($fp);
274
+ fclose($lc);
275
+
276
+ if ($success) {
277
+ Mage::getConfig()->saveConfig('recommender/settings/strands_catalog_time',date(DATE_RSS));
278
+ Mage::getConfig()->saveConfig('recommender/settings/strands_catalog_upload_now',0);
279
+ }
280
+
281
+ }
282
+
283
+
284
+ /**
285
+ * Method to retrive cart collection
286
+ *
287
+ * @return Mage_Sales_Model_Qoute?
288
+ */
289
+ protected function getCartItems()
290
+ {
291
+ return Mage::getSingleton('checkout/session')->getQuote()->getItemsCollection();
292
+ }
293
+
294
+
295
+ }
296
+
297
+ ?>
app/code/community/Strands/Recommender/etc/config.xml ADDED
@@ -0,0 +1,146 @@
1
+ <?xml version="1.0"?>
2
+ <config>
3
+ <modules>
4
+ <Strands_Recommender>
5
+ <version>1.1.1</version>
6
+ </Strands_Recommender>
7
+ </modules>
8
+
9
+ <global>
10
+ <models>
11
+ <recommender>
12
+ <class>Strands_Recommender_Model</class>
13
+ </recommender>
14
+ </models>
15
+ <blocks>
16
+ <recommender>
17
+ <class>Strands_Recommender_Block</class>
18
+ </recommender>
19
+ </blocks>
20
+ <helpers>
21
+ <recommender>
22
+ <class>Strands_Recommender_Helper</class>
23
+ </recommender>
24
+ </helpers>
25
+ </global>
26
+
27
+ <frontend>
28
+ <layout>
29
+ <updates>
30
+ <recommender>
31
+ <file>strands_recommender.xml</file>
32
+ </recommender>
33
+ </updates>
34
+ </layout>
35
+ <events>
36
+ <checkout_cart_product_add_after>
37
+ <observers>
38
+ <recommender_product_add_observer>
39
+ <type>singleton</type>
40
+ <class>recommender/observer</class>
41
+ <method>eventCartChange</method>
42
+ </recommender_product_add_observer>
43
+ </observers>
44
+ </checkout_cart_product_add_after>
45
+ <customer_login>
46
+ <observers>
47
+ <recommender_customer_login_observer>
48
+ <type>singleton</type>
49
+ <class>recommender/observer</class>
50
+ <method>eventUserLogin</method>
51
+ </recommender_customer_login_observer>
52
+ </observers>
53
+ </customer_login>
54
+ <controller_action_postdispatch_catalogsearch_result_index>
55
+ <observers>
56
+ <recommender_postdispatch_observer>
57
+ <type>singleton</type>
58
+ <class>recommender/observer</class>
59
+ <method>eventPostDispatchSearch</method>
60
+ </recommender_postdispatch_observer>
61
+ </observers>
62
+ </controller_action_postdispatch_catalogsearch_result_index>
63
+ <controller_action_postdispatch_catalog_product_view>
64
+ <observers>
65
+ <recommender_postdispatch_observer>
66
+ <type>singleton</type>
67
+ <class>recommender/observer</class>
68
+ <method>eventPostDispatchProductView</method>
69
+ </recommender_postdispatch_observer>
70
+ </observers>
71
+ </controller_action_postdispatch_catalog_product_view>
72
+ <sales_order_payment_place_end>
73
+ <observers>
74
+ <recommender_pay_observer>
75
+ <type>singleton</type>
76
+ <class>recommender/observer</class>
77
+ <method>eventPayInvoice</method>
78
+ </recommender_pay_observer>
79
+ </observers>
80
+ </sales_order_payment_place_end>
81
+ <wishlist_add_product>
82
+ <observers>
83
+ <recommender_wishlist_observer>
84
+ <type>singleton</type>
85
+ <class>recommender/observer</class>
86
+ <method>eventWishlistAdd</method>
87
+ </recommender_wishlist_observer>
88
+ </observers>
89
+ </wishlist_add_product>
90
+ </events>
91
+ <routers>
92
+ <recommender>
93
+ <use>admin</use>
94
+ <args>
95
+ <module>Strands_Recommender</module>
96
+ <frontName>recommender</frontName>
97
+ </args>
98
+ </recommender>
99
+ </routers>
100
+ </frontend>
101
+
102
+ <adminhtml>
103
+ <events>
104
+ <controller_action_predispatch_adminhtml_system_config_save>
105
+ <observers>
106
+ <recommender_predispatch_observer>
107
+ <type>singleton</type>
108
+ <class>recommender/observer</class>
109
+ <method>eventPreDispatch</method>
110
+ </recommender_predispatch_observer>
111
+ </observers>
112
+ </controller_action_predispatch_adminhtml_system_config_save>
113
+ </events>
114
+ <acl>
115
+ <resources>
116
+ <all>
117
+ <title>Allow Everything</title>
118
+ </all>
119
+ <admin>
120
+ <children>
121
+ <system>
122
+ <children>
123
+ <config>
124
+ <children>
125
+ <recommender module="recommender">
126
+ <title>Strands Recommender</title>
127
+ </recommender>
128
+ </children>
129
+ </config>
130
+ </children>
131
+ </system>
132
+ </children>
133
+ </admin>
134
+ </resources>
135
+ </acl>
136
+ </adminhtml>
137
+ <crontab>
138
+ <jobs>
139
+ <recommender_apply_all>
140
+ <schedule><cron_expr>* * * * *</cron_expr></schedule>
141
+ <run><model>recommender/observer::uploadCatalog</model></run>
142
+ </recommender_apply_all>
143
+
144
+ </jobs>
145
+ </crontab>
146
+ </config>
app/code/community/Strands/Recommender/etc/system.xml ADDED
@@ -0,0 +1,129 @@
1
+ <?xml version="1.0"?>
2
+ <config>
3
+ <sections>
4
+ <recommender translate="label" module="recommender">
5
+ <label>Strands Recommender</label>
6
+ <tab>advanced</tab>
7
+ <frontend_type>text</frontend_type>
8
+ <sort_order>999</sort_order>
9
+ <show_in_default>1</show_in_default>
10
+ <show_in_website>1</show_in_website>
11
+ <show_in_store>1</show_in_store>
12
+ <groups>
13
+ <settings translate="label">
14
+ <label>Recommender Settings</label>
15
+ <frontend_type>text</frontend_type>
16
+ <show_in_default>1</show_in_default>
17
+ <show_in_website>1</show_in_website>
18
+ <show_in_store>1</show_in_store>
19
+ <fields>
20
+ <active>
21
+ <label>Enable</label>
22
+ <frontend_type>select</frontend_type>
23
+ <source_model>adminhtml/system_config_source_yesno</source_model>
24
+ <sort_order>1</sort_order>
25
+ <show_in_default>1</show_in_default>
26
+ <show_in_website>1</show_in_website>
27
+ <show_in_store>1</show_in_store>
28
+ </active>
29
+ <log>
30
+ <label>Log Api Calls</label>
31
+ <comment><![CDATA[Do no select yes unless instructed to by Strands Recommender Client Services]]></comment>
32
+ <frontend_type>select</frontend_type>
33
+ <source_model>adminhtml/system_config_source_yesno</source_model>
34
+ <sort_order>2</sort_order>
35
+ <show_in_default>0</show_in_default>
36
+ <show_in_website>0</show_in_website>
37
+ <show_in_store>0</show_in_store>
38
+ </log>
39
+ <strands_api_id translate="label,comment">
40
+ <label>Strands API ID</label>
41
+ <comment><![CDATA[Strands API ID provided by Strands]]></comment>
42
+ <frontend_type>text</frontend_type>
43
+ <sort_order>3</sort_order>
44
+ <show_in_default>1</show_in_default>
45
+ <show_in_website>1</show_in_website>
46
+ <show_in_store>1</show_in_store>
47
+ </strands_api_id>
48
+ <strands_customer_token translate="label,comment">
49
+ <label>Strands Customer Validation Token</label>
50
+ <comment><![CDATA[Strands Customer Validation Token provided by Strands]]></comment>
51
+ <frontend_type>text</frontend_type>
52
+ <sort_order>4</sort_order>
53
+ <show_in_default>1</show_in_default>
54
+ <show_in_website>1</show_in_website>
55
+ <show_in_store>1</show_in_store>
56
+ </strands_customer_token>
57
+ <strands_login translate="label,comment">
58
+ <label>Strands Login</label>
59
+ <comment><![CDATA[Strands login provided by Strands]]></comment>
60
+ <frontend_type>text</frontend_type>
61
+ <sort_order>5</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
+ </strands_login>
66
+ <strands_password translate="label,comment">
67
+ <label>Strands Password</label>
68
+ <comment><![CDATA[Strands password chosen, the same used in Strands signup]]></comment>
69
+ <frontend_type>password</frontend_type>
70
+ <sort_order>6</sort_order>
71
+ <show_in_default>1</show_in_default>
72
+ <show_in_website>1</show_in_website>
73
+ <show_in_store>1</show_in_store>
74
+ </strands_password>
75
+ <freedirectory>
76
+ <label>Free Directory</label>
77
+ <comment><![CDATA[Through a special partnership with eMediaSales, Strands Recommender users on Miva Merchant can receive a free account and listing at http://www.emediastores.com, the premier Miva Merchant store and product directory on the internet.]]></comment>
78
+ <frontend_type>select</frontend_type>
79
+ <frontend_model>recommender/system_config_form_field</frontend_model>
80
+ <source_model>adminhtml/system_config_source_yesno</source_model>
81
+ <sort_order>7</sort_order>
82
+ <show_in_default>0</show_in_default>
83
+ <show_in_website>0</show_in_website>
84
+ <show_in_store>0</show_in_store>
85
+ </freedirectory>
86
+ <freedirectory_hidden>
87
+ <label>Free Directory Hidden</label>
88
+ <frontend_type>select</frontend_type>
89
+ <source_model>adminhtml/system_config_source_yesno</source_model>
90
+ <sort_order>8</sort_order>
91
+ <show_in_default>0</show_in_default>
92
+ <show_in_website>0</show_in_website>
93
+ <show_in_store>0</show_in_store>
94
+ </freedirectory_hidden>
95
+ <strands_desired_catalog_time translate="label,comment">
96
+ <label>Time to upload catalog</label>
97
+ <comment><![CDATA[Select the time (only hour in GMT) when you want your catalog to be uploaded to Strands Recommender (daily)]]></comment>
98
+ <frontend_type>select</frontend_type>
99
+ <source_model>recommender/numberoption</source_model>
100
+ <sort_order>9</sort_order>
101
+ <show_in_default>1</show_in_default>
102
+ <show_in_website>1</show_in_website>
103
+ <show_in_store>1</show_in_store>
104
+ </strands_desired_catalog_time>
105
+ <strands_catalog_time translate="label,comment">
106
+ <label>Last catalog upload</label>
107
+ <comment><![CDATA[Shows the time when the last catalog was successfully uploaded to Strands Recommender (DO NOT FILL!)]]></comment>
108
+ <frontend_type>text</frontend_type>
109
+ <sort_order>11</sort_order>
110
+ <show_in_default>1</show_in_default>
111
+ <show_in_website>1</show_in_website>
112
+ <show_in_store>1</show_in_store>
113
+ </strands_catalog_time>
114
+ <strands_catalog_upload_now translate="label,comment">
115
+ <label>Upload catalog now</label>
116
+ <comment><![CDATA[Select Yes if you want to upload your catalog right now]]></comment>
117
+ <frontend_type>select</frontend_type>
118
+ <source_model>adminhtml/system_config_source_yesno</source_model>
119
+ <sort_order>10</sort_order>
120
+ <show_in_default>1</show_in_default>
121
+ <show_in_website>1</show_in_website>
122
+ <show_in_store>1</show_in_store>
123
+ </strands_catalog_upload_now>
124
+ </fields>
125
+ </settings>
126
+ </groups>
127
+ </recommender>
128
+ </sections>
129
+ </config>
app/design/frontend/default/default/layout/strands_recommender.xml ADDED
@@ -0,0 +1,47 @@
1
+ <?xml version="1.0"?>
2
+ <layout version="1.0.0">
3
+
4
+
5
+ <!--
6
+ Load Recommender on the homepage
7
+ -->
8
+ <cms_index_index>
9
+
10
+ </cms_index_index>
11
+
12
+ <!--
13
+ Load Recommender on the product page
14
+ -->
15
+ <catalog_product_view>
16
+
17
+ </catalog_product_view>
18
+
19
+ <!--
20
+ Load Recommender on the category page
21
+ -->
22
+ <catalog_category_view>
23
+
24
+ </catalog_category_view>
25
+
26
+ <!--
27
+ Load Recommender on the shopping cart page
28
+ -->
29
+ <checkout_cart_index>
30
+
31
+ </checkout_cart_index>
32
+
33
+ <!--
34
+ Load Recommender on the success purchase page for onepage checkout page
35
+ -->
36
+ <checkout_onepage_success>
37
+
38
+ </checkout_onepage_success>
39
+
40
+ <!--
41
+ Load Recommender on the success purchase page for multishipping checkout page
42
+ -->
43
+ <checkout_multishipping_success>
44
+
45
+ </checkout_multishipping_success>
46
+
47
+ </layout>
app/design/frontend/default/default/template/strands/recommender/widget.phtml ADDED
@@ -0,0 +1,5 @@
1
+ <div class="strandsRecs"
2
+ tpl="<?php echo $this->getWidgetName() ?>"
3
+ <?php echo ($this->getStrandsId()) ? "user=\"{$this->getStrandsId()}\"" : '' ?>
4
+ <?php echo ($this->getItem()) ? "item=\"{$this->getItem()}\"" : '' ?>
5
+ <?php echo ($this->getDFilter()) ? "dfilter=\"{$this->getDFilter()}\"" : '' ?>></div>
app/etc/modules/Strands_Recommender.xml ADDED
@@ -0,0 +1,9 @@
1
+ <?xml version="1.0"?>
2
+ <config>
3
+ <modules>
4
+ <Strands_Recommender>
5
+ <active>true</active>
6
+ <codePool>community</codePool>
7
+ </Strands_Recommender>
8
+ </modules>
9
+ </config>
package.xml ADDED
@@ -0,0 +1,35 @@
1
+ <?xml version="1.0"?>
2
+ <package>
3
+ <name>StrandsRecommender</name>
4
+ <version>1.3.3</version>
5
+ <stability>stable</stability>
6
+ <license uri="http://www.opensource.org/licenses/osl-3.0.php">OSL v3.0</license>
7
+ <channel>community</channel>
8
+ <extends/>
9
+ <summary>Strand Recommender is the leading personalization and PRODUCT RECOMMENDATIONS service on the web today for small and mid-sized stores, bringing you the easiest and most cost effective way to personalize your customers shopping experience, automate up-sells and cross-sells, boost conversions, and develop actionable user profiles.</summary>
10
+ <description>Strands Recommender helps retailers increase customer retention and conversion rates through personalized product recommendations. The recommender platform captures product attributes, user behavior, and third party data like ratings and reviews, and delivers the right suggestions to users throughout the shopping experience. Strands Recommender is an independent business unit of Strands Labs, Inc., an industry leader in the personalization space, Strands today has over six years of relevant industry experience, over 100 employees, and a growing list of retail customers such as Skymall, TravelSmith, Kitson, FootwearEtc, and many other IR500 customers. http://recommender.strands.com
11
+
12
+
13
+ Features:
14
+ 30-day free trial, month-to-month or annual plans
15
+ Automated up-sell &amp; cross-sell recommendations based on crowd behavior and product attributes
16
+ Personalized recommendations based on individual behavior and similar individual profiles
17
+ Visible and actionable user profiles
18
+ Email recommendations and targeted campaigns
19
+ Product and user-level analytics showing impact &amp; ROI
20
+ Merchant-defined promotions
21
+ Rules &amp; filters to "curate" recommendations
22
+ Algorithm controls and configuration options.
23
+ Highly scalable, tolerant of millions to tens of millions of products &amp; users
24
+ Integrates with BazaarVoice, PowerReviews, RateVoice.
25
+ API for developers and affiliates</description>
26
+ <notes>First release of the Strands Recommender plugin for the Magento community.
27
+
28
+ Visit http://recommender.strands.com/magento</notes>
29
+ <authors><author><name>Strands Recommender</name><user>auto-converted</user><email>support-sbs@strands.com</email></author></authors>
30
+ <date>2010-09-23</date>
31
+ <time>13:19:08</time>
32
+ <contents><target name="magedesign"><dir name="frontend"><dir name="default"><dir name="default"><dir name="layout"><file name="strands_recommender.xml" hash="e4452ce114e4ac6f8c3b42c0f6a83542"/></dir><dir name="template"><dir name="strands"><dir name="recommender"><file name="widget.phtml" hash="f70046679504792dcea57b1a04de2991"/></dir></dir></dir></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="Strands_Recommender.xml" hash="bd28f5b01dfa3aa711c2484e68b3b4c8"/></dir></target><target name="magecommunity"><dir name="Strands"><dir name="Recommender"><dir name="Block"><dir name="System"><dir name="Config"><dir name="Form"><file name="Field.php" hash="08ab8029c8b1fda4b82c2b75babc69b2"/></dir></dir></dir><file name="Js.php" hash="4e861c83345e819fcf87f4082a9135e8"/><file name="Widget.php" hash="62a4d6c7f0187bf5a6f3d4670c091874"/></dir><dir name="etc"><file name="config.xml" hash="6116fd2544b18eaa09481403a37814bd"/><file name="system.xml" hash="8215afaee350a58e633b660f1191c570"/></dir><dir name="Helper"><file name="Abstract.php" hash="fd88693cae72710e81b151ad84278584"/><file name="Data.php" hash="9f97536deb3727cfc4f9822adca9a826"/><file name="Logger.php" hash="ba5999655822a2b1663c98cf3f44de6a"/></dir><dir name="Model"><file name="Abstract.php" hash="0b8be14b6097f4dd8b2caab49f271857"/><file name="Api.php" hash="4a8dc80ab1aa5046adb47cd1064b3884"/><file name="Numberoption.php" hash="34ffcbfe6b4004b213013b12ddaa6abf"/><file name="Observer.php" hash="c3ade1e22317c800a0937ac1cc10e2cf"/></dir></dir></dir></target></contents>
33
+ <compatible/>
34
+ <dependencies/>
35
+ </package>