Vufind_Vumatch - Version 1.0.0

Version Notes

Initial stable release

Download this release

Release Info

Developer DeepVu
Extension Vufind_Vumatch
Version 1.0.0
Comparing to
See all releases


Version 1.0.0

app/code/community/Vufind/Vumatch/Block/Widget.php ADDED
@@ -0,0 +1,96 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ Class Vufind_Vumatch_Block_Widget extends Mage_Core_Block_Template
4
+ {
5
+ protected $_checkout = null;
6
+ protected $_quote = null;
7
+ protected $_template = "vufind/vumatch/widget.phtml";
8
+ protected $helper = null;
9
+
10
+ public function _construct()
11
+ {
12
+ parent::_construct();
13
+ $this->helper = Mage::helper('vumatch');
14
+ }
15
+
16
+ protected function _toHtml()
17
+ {
18
+ $model = Mage::getModel('vumatch/abstract');
19
+ if (!$model->isActive()) {
20
+ return '';
21
+ }
22
+
23
+ if (!$this->hasData('widget_name'))
24
+ $this->setWidgetName($this->_getTemplate());
25
+
26
+ return parent::_toHtml();
27
+ }
28
+
29
+ protected function _getTemplate()
30
+ {
31
+ switch($this->helper->getCurrentPage()) {
32
+ case "catalog_product_view":
33
+ return "catalog_product_view";
34
+ break;
35
+
36
+ default:
37
+ return "cms_index_index";
38
+ break;
39
+ }
40
+ }
41
+
42
+ private function getProduct()
43
+ {
44
+ if (!$this->hasData('product')) {
45
+ $this->setData('product', Mage::registry('product'));
46
+ }
47
+ return $this->getData('product');
48
+ }
49
+
50
+ public function getHtmlCode()
51
+ {
52
+ $product = $this->getProduct();
53
+ $productId = $product->getId();
54
+
55
+ $api = Mage::getSingleton('vumatch/api');
56
+ $ret = $api->getSimilarProducts($productId);
57
+
58
+ $html = '';
59
+ $total = 0;
60
+
61
+ if($ret['success'] == false) {
62
+ return $html;
63
+ }
64
+
65
+ $recommendations = $ret['message'];
66
+ $recommendations = json_decode($recommendations, true);
67
+ foreach($recommendations as $recommendation) {
68
+ $productSku = $recommendation['id'];
69
+ $product = Mage::getModel('catalog/product')->load($product->getIdBySku($productSku));
70
+ if(!empty($product)) {
71
+
72
+ $visibility = $product->getVisibility();
73
+ if ($visibility != 4) {
74
+ continue;
75
+ }
76
+ //if($total < 1){ continue; }
77
+ $url = $product->getProductUrl();
78
+
79
+ $html .= '<div style="text-align: center; display: inline-block;width:140px;vertical-align:top;">';
80
+ $html .= '<a class="product-image" href="' . $url . '"><img width="135" src="' .
81
+ $product->getImageUrl() . '" />' . $product->getName();
82
+ $html .= '</a></div>&nbsp;';
83
+
84
+ $total = $total + 1;
85
+ if ($total == 7) break;
86
+ }
87
+ }
88
+
89
+ if($html == '') $html = 'No recommendations for now';
90
+ return $html;
91
+ }
92
+ }
93
+
94
+
95
+ ?>
96
+
app/code/community/Vufind/Vumatch/Helper/Data.php ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ Class Vufind_Vumatch_Helper_Data 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/Vufind/Vumatch/Model/Abstract.php ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ Class Vufind_Vumatch_Model_Abstract extends Mage_Core_Model_Abstract
4
+ {
5
+
6
+ public function getVersion()
7
+ {
8
+ $version = Mage::getConfig()->getNode('modules')->Vufind_Vumatch->version;
9
+ return $version;
10
+
11
+ }
12
+
13
+ public function getVufindId()
14
+ {
15
+ if (!$this->hasData('vufind_id')) {
16
+ $session = Mage::getSingleton("customer/session");
17
+
18
+ if ($session->isLoggedIn()) {
19
+ if (($email = $session->getCustomer()->getEmail()) != '') {
20
+ $this->setTrouvusId($email);
21
+ }else{
22
+ $this->setTrouvusId($session->getCustomerId());
23
+ }
24
+ } else {
25
+ $cookieName = 'vufind_usr';
26
+ $cookieVal = Mage::app()->getFrontController()->getRequest()->getCookie($cookieName);
27
+
28
+ if (strlen($cookieVal))
29
+ return $cookieVal;
30
+ else {
31
+ $newCookie = $this->create_anonymous_cookie();
32
+ Mage::getModel('core/cookie')->set($cookieName, $newCookie, 86400*100, '/', null, null, false);
33
+ return $newCookie;
34
+ }
35
+ }
36
+ }
37
+ return $this->getData('vufind_id');
38
+ }
39
+
40
+ public function getCurrentProduct()
41
+ {
42
+ if (!$this->hasData('product')) {
43
+ $this->setData('product', Mage::registry('product'));
44
+ }
45
+ return $this->getData('product');
46
+ }
47
+
48
+ private function create_anonymous_cookie()
49
+ {
50
+ $cookie = 'usr_'.$this->ms_time().'_'.rand(0,100000);
51
+ return $cookie;
52
+ }
53
+
54
+ private function ms_time()
55
+ {
56
+ $timeday = gettimeofday();
57
+ $sec = intval($timeday['sec']);
58
+ $msec = intval(floor($timeday['usec']/1000));
59
+ if (strlen($msec) == 2) $msec = '0'.$msec;
60
+ elseif (strlen($msec) == 1) $msec = '00'.$msec;
61
+
62
+ return $sec.$msec;
63
+ }
64
+
65
+ public function isActive()
66
+ {
67
+ if (!Mage::getStoreConfigFlag('vumatch/account/active')) return false;
68
+ if (strlen($this->getApiKey()) < 1) return false;
69
+ if (strlen($this->getApiToken()) < 1) return false;
70
+ if (strlen($this->getCustomerId()) < 1) return false;
71
+ return true;
72
+ }
73
+
74
+ public function getApiKey()
75
+ {
76
+ if (!$this->hasData('vumatch_api_key')) {
77
+ $this->setData('vumatch_api_key', Mage::getStoreConfig('vumatch/account/api_key'));
78
+ }
79
+ return $this->getData('vumatch_api_key');
80
+ }
81
+
82
+ public function getApiToken()
83
+ {
84
+ if (!$this->hasData('vumatch_api_token')) {
85
+ $this->setData('vumatch_api_token', Mage::getStoreConfig('vumatch/account/api_token'));
86
+ }
87
+ return $this->getData('vumatch_api_token');
88
+ }
89
+
90
+ public function getCustomerId()
91
+ {
92
+ if (!$this->hasData('vumatch_customer_id')) {
93
+ $this->setData('vumatch_customer_id', Mage::getStoreConfig('vumatch/account/customer_id'));
94
+ }
95
+ return $this->getData('vumatch_customer_id');
96
+ }
97
+ }
98
+
99
+ ?>
app/code/community/Vufind/Vumatch/Model/Api.php ADDED
@@ -0,0 +1,79 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ Class Vufind_Vumatch_Model_Api extends Vufind_Vumatch_Model_Abstract
4
+ {
5
+ public function sendView($sku, $customerId, $category, $imageUrl)
6
+ {
7
+ $url = "http://api7.vufind.com/api/magento/log?uid=$customerId&sku=$sku&url=$imageUrl&c=$category";
8
+
9
+ $curl = curl_init();
10
+ curl_setopt($curl, CURLOPT_URL, $url);
11
+ curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
12
+ curl_setopt($curl, CURLOPT_USERAGENT, "Magento VuMatch Visual Recommendations");
13
+ $res = curl_exec($curl);
14
+ return $res;
15
+ }
16
+
17
+ public function getSimilarProducts($productId)
18
+ {
19
+ $product = Mage::getModel('catalog/product')->load($productId);
20
+ $imageUrl = Mage::getModel('catalog/product_media_config')->getMediaUrl($product->getImage());
21
+ $catalogName = "";
22
+ $cats = $product->getCategoryIds();
23
+ $catsCounter = 1;
24
+ $catsLength = sizeof($cats);
25
+ foreach ($cats as $category_id) {
26
+ $_cat = Mage::getModel('catalog/category')->load($category_id) ;
27
+ $category = $_cat->getName();
28
+ if(strlen($category) > 0 && ($catsCounter == 1 || $catsCounter == $catsLength)) {
29
+ $catalogName .= $category;
30
+ if($catsCounter < $catsLength) $catalogName .="_";
31
+ }
32
+ $catsCounter += 1;
33
+ }
34
+ $catalogName = preg_replace('/\%/','',$catalogName);
35
+ $catalogName = preg_replace('/\@/','',$catalogName);
36
+ $catalogName = preg_replace('/\&/','_and_',$catalogName);
37
+ $catalogName = preg_replace('/\s[\s]+/','',$catalogName);
38
+ $catalogName = preg_replace('/[\s\W]+/','',$catalogName);
39
+ $catalogName = preg_replace('/^[\-]+/','',$catalogName);
40
+ $catalogName = preg_replace('/[\-]+$/','',$catalogName);
41
+ $catalogName = strtolower($catalogName);
42
+
43
+ $url = "http://api9.vufind.com/vumatch/vumatch.php?app_key=".$this->getApiKey()."&token=".$this->getApiToken()."&customer_id=".$this->getCustomerId()."&cat=".$catalogName."&url=".$imageUrl;
44
+ return $this->makeCall($url, 'GET');
45
+ }
46
+
47
+ private function makeCall($url)
48
+ {
49
+ $ret = array('success' => true);
50
+ try {
51
+ $curl = curl_init();
52
+ curl_setopt($curl, CURLOPT_URL, $url);
53
+
54
+ curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
55
+ curl_setopt($curl, CURLOPT_USERAGENT, "Magento VuMatch Visual Recommendations");
56
+
57
+ $res = curl_exec($curl);
58
+ $res = json_decode($res, true);
59
+
60
+ if($res["Status"] == false) {
61
+ $ret['success'] = false;
62
+ $ret['message'] = $res["Error"]["Message"];
63
+ return $ret;
64
+ }
65
+
66
+ $ret['message'] = $res['Data']['VufindRecommends'];
67
+
68
+ curl_close($curl);
69
+ } catch(Exception $e) {
70
+ $ret['success'] = false;
71
+ $ret['message'] = $e->getMessage();
72
+ }
73
+
74
+ return $ret;
75
+ }
76
+ }
77
+
78
+ ?>
79
+
app/code/community/Vufind/Vumatch/Model/Observer.php ADDED
@@ -0,0 +1,269 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ Class Vufind_Vumatch_Model_Observer extends Vufind_Vumatch_Model_Abstract
4
+ {
5
+ protected function _construct()
6
+ {
7
+ parent::_construct();
8
+ }
9
+
10
+
11
+ //for logging once a product recommendation is viewed...
12
+ public function eventPostDispatchProductView($observer)
13
+ {
14
+ if (!$this->isActive()) return;
15
+ $currentProduct = $this->getCurrentProduct();
16
+ $sku = $currentProduct->getSku();
17
+ $imageUrl = Mage::getModel('catalog/product_media_config')->getMediaUrl($currentProduct->getImage());
18
+ $customerId = $this->getCustomerId();
19
+
20
+ $catalogName = ""; //combined
21
+ $category = ""; //single
22
+ $cats = $currentProduct->getCategoryIds();
23
+ $catsCounter = 1;
24
+ $catsLength = sizeof($cats);
25
+ foreach ($cats as $category_id) {
26
+ $_cat = Mage::getModel('catalog/category')->load($category_id) ;
27
+ $category = $_cat->getName();
28
+ if(strlen($category) > 0 && ($catsCounter == 1 || $catsCounter == $catsLength)) {
29
+ $catalogName .= $category;
30
+ if($catsCounter < $catsLength) $catalogName .="_";
31
+ }
32
+ $catsCounter += 1;
33
+ }
34
+ $catalogName = preg_replace('/\%/','',$catalogName);
35
+ $catalogName = preg_replace('/\@/','',$catalogName);
36
+ $catalogName = preg_replace('/\&/','_and_',$catalogName);
37
+ $catalogName = preg_replace('/\s[\s]+/','',$catalogName);
38
+ $catalogName = preg_replace('/[\s\W]+/','',$catalogName);
39
+ $catalogName = preg_replace('/^[\-]+/','',$catalogName);
40
+ $catalogName = preg_replace('/[\-]+$/','',$catalogName);
41
+ $catalogName = strtolower($catalogName);
42
+
43
+ $api = Mage::getSingleton('vumatch/api');
44
+ $result = $api->sendView($sku, $customerId, $catalogName, $imageUrl);
45
+
46
+ return $this;
47
+ }
48
+
49
+ private function getPackageTheme($termDB)
50
+ {
51
+ $coreResource = Mage::getSingleton('core/resource');
52
+ $read = $coreResource->getConnection('core_read');
53
+ $config_data = $coreResource->getTableName ('core_config_data');
54
+
55
+ $termDB = '"'.$termDB.'"';
56
+ $sql = "SELECT value FROM $config_data WHERE path=$termDB";
57
+ $resultDB = $read->fetchAll($sql);
58
+
59
+ if (count($resultDB) == 0){
60
+ $result = 'default';
61
+ } else{
62
+ $result = $resultDB[0]['value'];
63
+ if ($result == '' || $result == null ){
64
+ $result = 'default';
65
+ }
66
+ }
67
+ return $result;
68
+ }
69
+
70
+ private function getDirectory($package, $theme, $type)
71
+ {
72
+ $absPath = Mage::getBaseDir() . '/app/design/frontend/';
73
+
74
+ if ($package=='' || !file_exists($absPath.$package) ) {
75
+ $package = 'default';
76
+ }
77
+ if ($theme=='' || !file_exists($absPath.$package.$theme)){
78
+ $theme = 'default';
79
+ }
80
+
81
+ $dirFinalPT = $absPath.$package.'/'.$theme;
82
+
83
+ if (!file_exists($dirFinalPT)) {
84
+ // It is not possible to locate the right directory
85
+ Mage::getConfig()->saveConfig('vumatch/setup/packagetheme','Not possible to locate the right package/theme in '.$dirFinalPT);
86
+ return;
87
+ }
88
+
89
+ $dirFinalPTtype = $dirFinalPT.'/'.$type;
90
+
91
+ if (!file_exists($dirFinalPTtype)) {
92
+ mkdir($dirFinalPTtype, 0766, true);
93
+ }
94
+
95
+ if ($type=="template") {
96
+ if (!file_exists($dirFinalPTtype.'/vufind')) {
97
+ mkdir($dirFinalPTtype."/vufind", 0766, true);
98
+ }
99
+ if (!file_exists($dirFinalPTtype.'/vufind/vumatch')) {
100
+ mkdir($dirFinalPTtype."/vufind/vumatch", 0766, true);
101
+ }
102
+ }
103
+
104
+ if (!file_exists($dirFinalPTtype)) {
105
+ Mage::getConfig()->saveConfig('vumatch/setup/packagetheme', $type . ' folder is not available in ' . $dirFinalPT);
106
+ return;
107
+ }
108
+
109
+ return $dirFinalPTtype;
110
+ }
111
+
112
+ private function getHandlerUpdate($handler) {
113
+ $structural = 'footer';
114
+ $position = 'before';
115
+ $block = '-';
116
+
117
+ $xml='<'.$handler.'>
118
+ <reference name="'.$structural.'">
119
+ <block type="vumatch/widget" name="vumatch.widget" '.$position.'="'.$block.'"/>
120
+ </reference>
121
+ </'.$handler.'>';
122
+
123
+ return $xml;
124
+ }
125
+
126
+ public function eventPostDispatch($observer)
127
+ {
128
+ $cont = $observer->getEvent()->getControllerAction();
129
+
130
+ if ($cont->getRequest()->getParam('section') !== 'vumatch') {
131
+ return $this;
132
+ }
133
+
134
+ //first see if catalog sync is requested and then upload it
135
+ if (Mage::getStoreConfigFlag('vumatch/account/sync_catalog')) {
136
+ $products = Mage::getModel('catalog/product')->getCollection();
137
+ $products->addAttributeToSelect('sku');
138
+ $products->addAttributeToSelect('type_id');
139
+
140
+ $catalogCSV = "sku,category,name,price,url\n";
141
+ $counter = 0;
142
+ foreach($products as $prod) {
143
+ try{
144
+ $product = Mage::getModel('catalog/product')->load($prod->getId());
145
+ $visibility = $product->getVisibility();
146
+ if ($visibility != 4) {
147
+ continue;
148
+ }
149
+ $category = ""; //single category
150
+ $catalogName = ""; //combined
151
+ $cats = $product->getCategoryIds();
152
+ $catsCounter = 1;
153
+ $catsLength = sizeof($cats);
154
+ foreach ($cats as $category_id) {
155
+ $_cat = Mage::getModel('catalog/category')->load($category_id) ;
156
+ $category = $_cat->getName();
157
+ if(strlen($category) > 0 && ($catsCounter == 1 || $catsCounter == $catsLength)) {
158
+ $catalogName .= $category;
159
+ if($catsCounter < $catsLength) $catalogName .="_";
160
+ }
161
+ $catsCounter += 1;
162
+ }
163
+ $catalogName = preg_replace('/\%/','',$catalogName);
164
+ $catalogName = preg_replace('/\@/','',$catalogName);
165
+ $catalogName = preg_replace('/\&/','_and_',$catalogName);
166
+ $catalogName = preg_replace('/\s[\s]+/','',$catalogName);
167
+ $catalogName = preg_replace('/[\s\W]+/','',$catalogName);
168
+ $catalogName = preg_replace('/^[\-]+/','',$catalogName);
169
+ $catalogName = preg_replace('/[\-]+$/','',$catalogName);
170
+ $catalogName = strtolower($catalogName);
171
+
172
+
173
+ $sku = $product->getSku();
174
+ $name = $product->getName();
175
+ $price = $product->getPrice();
176
+ $imageUrl = Mage::getModel('catalog/product_media_config')->getMediaUrl($product->getImage());
177
+ if(strlen($imageUrl) < 1) continue;
178
+ if(strlen($catalogName) < 1) continue;
179
+ $catalogCSV .= $sku.",".$catalogName.",".$name.",".$price.",".$imageUrl."\n";
180
+ $counter += 1;
181
+ } catch(Exception $e) {
182
+ Mage::log($e->getMessage());
183
+ continue;
184
+ }
185
+ }
186
+
187
+ $csvPath = Mage::getBaseDir()."/app/code/community/Vufind/Vumatch/Helper/catalog.csv";
188
+ $file = fopen($csvPath, 'w');
189
+ fwrite($file, $catalogCSV);
190
+ fclose($file);
191
+ chmod($csvPath,0755);
192
+
193
+ $customer_id = $this->getCustomerId();
194
+ $api_key = $this->getApiKey();
195
+ $api_token = $this->getApiToken();
196
+
197
+ $headers = array("Content-Type:multipart/form-data"); // cURL headers for file uploading
198
+ $postfields = array("catalog" => "@$csvPath", "customer_id" => $customer_id, "api_key" => $api_key, "api_token" => $api_token);
199
+ $ch = curl_init();
200
+ $options = array(
201
+ CURLOPT_URL => "http://api7.vufind.com/api/magento/upload",
202
+ CURLOPT_HEADER => true,
203
+ CURLOPT_POST => 1,
204
+ CURLOPT_HTTPHEADER => $headers,
205
+ CURLOPT_POSTFIELDS => $postfields,
206
+ CURLOPT_RETURNTRANSFER => true,
207
+ CURLOPT_USERAGENT => "Magento VuMatch Visual Recommendations"
208
+ ); // cURL options
209
+
210
+ curl_setopt_array($ch, $options);
211
+ $res = curl_exec($ch);
212
+
213
+ $config = Mage::getModel('core/config');
214
+ $config->saveConfig('vumatch/account/sync_catalog', '0');
215
+ Mage::app()->getConfig()->reinit();
216
+ }
217
+ }
218
+
219
+ public function eventPreDispatch($observer)
220
+ {
221
+ $cont = $observer->getEvent()->getControllerAction();
222
+
223
+ if ($cont->getRequest()->getParam('section') !== 'vumatch') {
224
+ return $this;
225
+ }
226
+
227
+ $htmlCode = $this->getHtmlCode();
228
+ if($htmlCode == '') {
229
+ return $this;
230
+ }
231
+
232
+
233
+ $package = $this->getPackageTheme('design/package/name');
234
+ $theme = $this->getPackageTheme('design/theme/default');
235
+
236
+ // layout
237
+ $dir = $this->getDirectory($package, $theme, 'layout');
238
+ $filename = $dir . '/vufind_vumatch.xml';
239
+ $file = fopen($filename, 'w');
240
+
241
+ $txt = '<?xml version="1.0"?>';
242
+ $txt .= '<layout version="1.0.0">';
243
+ $txt .= $this->getHandlerUpdate('catalog_product_view');
244
+ $txt .= '</layout>';
245
+
246
+ fwrite($file, $txt);
247
+ fclose($file);
248
+ chmod($filename,0755);
249
+
250
+ // template
251
+ $dir = $this->getDirectory($package, $theme, 'template');
252
+ $filename = $dir . '/vufind/vumatch/widget.phtml';
253
+ $file = fopen($filename, 'w');
254
+
255
+ $txt = '<div class="vufind-vumatch">';
256
+ $txt .= '<h2>You May Also Like</h2>';
257
+ $txt .= '<?php echo $htmlCode ?>';
258
+ $txt .= '<p align="right">Powered by <a href="http://deepvu.co">DeepVu</a></p><br/><br/></div>';
259
+
260
+ fwrite($file, $txt);
261
+ fclose($file);
262
+ chmod($filename,0755);
263
+
264
+ return $this;
265
+ }
266
+ }
267
+
268
+ ?>
269
+
app/code/community/Vufind/Vumatch/etc/config.xml ADDED
@@ -0,0 +1,93 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <config>
2
+ <modules>
3
+ <Vufind_Vumatch>
4
+ <version>0.1.0</version>
5
+ </Vufind_Vumatch>
6
+ </modules>
7
+ <global>
8
+ <blocks>
9
+ <vumatch>
10
+ <class>Vufind_Vumatch_Block</class>
11
+ </vumatch>
12
+ </blocks>
13
+ <models>
14
+ <vumatch>
15
+ <class>Vufind_Vumatch_Model</class>
16
+ </vumatch>
17
+ </models>
18
+ <helpers>
19
+ <vumatch>
20
+ <class>Vufind_Vumatch_Helper</class>
21
+ </vumatch>
22
+ </helpers>
23
+ </global>
24
+
25
+ <frontend>
26
+ <layout>
27
+ <updates>
28
+ <vumatch>
29
+ <file>vufind_vumatch.xml</file>
30
+ </vumatch>
31
+ </updates>
32
+ </layout>
33
+
34
+ <events>
35
+ <controller_action_postdispatch_catalog_product_view>
36
+ <observers>
37
+ <vumatch_postdispatch_observer>
38
+ <type>singleton</type>
39
+ <class>vumatch/observer</class>
40
+ <method>eventPostDispatchProductView</method>
41
+ </vumatch_postdispatch_observer>
42
+ </observers>
43
+ </controller_action_postdispatch_catalog_product_view>
44
+ </events>
45
+ </frontend>
46
+
47
+ <adminhtml>
48
+ <events>
49
+ <controller_action_predispatch_adminhtml_system_config_save>
50
+ <observers>
51
+ <vumatch_predispatch_observer>
52
+ <type>singleton</type>
53
+ <class>vumatch/observer</class>
54
+ <method>eventPreDispatch</method>
55
+ </vumatch_predispatch_observer>
56
+ </observers>
57
+ </controller_action_predispatch_adminhtml_system_config_save>
58
+ <controller_action_postdispatch_adminhtml_system_config_save>
59
+ <observers>
60
+ <vumatch_postdispatch_observer>
61
+ <type>singleton</type>
62
+ <class>vumatch/observer</class>
63
+ <method>eventPostDispatch</method>
64
+ </vumatch_postdispatch_observer>
65
+ </observers>
66
+ </controller_action_postdispatch_adminhtml_system_config_save>
67
+ </events>
68
+ <acl>
69
+ <resources>
70
+ <all>
71
+ <title>Allow Everything</title>
72
+ </all>
73
+ <admin>
74
+ <children>
75
+ <system>
76
+ <children>
77
+ <config>
78
+ <children>
79
+ <vumatch module="vumatch">
80
+ <title>Vufind Recommender</title>
81
+ </vumatch>
82
+ </children>
83
+ </config>
84
+ </children>
85
+ </system>
86
+ </children>
87
+ </admin>
88
+ </resources>
89
+ </acl>
90
+
91
+ </adminhtml>
92
+
93
+ </config>
app/code/community/Vufind/Vumatch/etc/system.xml ADDED
@@ -0,0 +1,84 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <config>
3
+ <tabs>
4
+ <vumatch translate="label" module="vumatch">
5
+ <label>Vumatch AI Recommendations</label>
6
+ <sort_order>100</sort_order>
7
+ </vumatch>
8
+ </tabs>
9
+ <sections>
10
+ <vumatch translate="label" module="vumatch">
11
+ <label>Vumatch</label>
12
+ <tab>vumatch</tab>
13
+ <sort_order>1000</sort_order>
14
+ <show_in_default>1</show_in_default>
15
+ <show_in_website>1</show_in_website>
16
+ <show_in_store>1</show_in_store>
17
+
18
+ <groups>
19
+ <account translate="label" module="vumatch">
20
+ <label>Configuration</label>
21
+ <frontend_type>text</frontend_type>
22
+ <expanded>1</expanded>
23
+ <sort_order>1000</sort_order>
24
+ <show_in_default>1</show_in_default>
25
+ <show_in_website>1</show_in_website>
26
+ <show_in_store>1</show_in_store>
27
+ <comment><![CDATA[Vumatch visual recommendations, check <a href="http://vufind.co/vumatch-demo.html" target="_blank">live demo</a><br><br>]]></comment>
28
+
29
+ <fields>
30
+ <active>
31
+ <label>Enable</label>
32
+ <comment><![CDATA[Set to Yes to activate Vumatch visual recommendations module]]></comment>
33
+ <frontend_type>select</frontend_type>
34
+ <source_model>adminhtml/system_config_source_yesno</source_model>
35
+ <sort_order>10</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
+ </active>
40
+ <api_key translate="label,comment">
41
+ <label>API Key*</label>
42
+ <comment><![CDATA[Your Vumatch API Key]]></comment>
43
+ <frontend_type>text</frontend_type>
44
+ <sort_order>20</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
+ </api_key>
49
+ <api_token translate="label,comment">
50
+ <label>API Token*</label>
51
+ <comment><![CDATA[Your Vumatch API Token]]></comment>
52
+ <frontend_type>text</frontend_type>
53
+ <sort_order>30</sort_order>
54
+ <show_in_default>1</show_in_default>
55
+ <show_in_website>1</show_in_website>
56
+ <show_in_store>1</show_in_store>
57
+ </api_token>
58
+ <customer_id translate="label,comment">
59
+ <label>Customer ID*</label>
60
+ <comment><![CDATA[Your Vufind Customer ID]]></comment>
61
+ <frontend_type>text</frontend_type>
62
+ <sort_order>40</sort_order>
63
+ <show_in_default>1</show_in_default>
64
+ <show_in_website>1</show_in_website>
65
+ <show_in_store>1</show_in_store>
66
+ </customer_id>
67
+ <sync_catalog>
68
+ <label>Sync catalog</label>
69
+ <comment><![CDATA[Sync catalog with Vufind. Required to serve recommendations]]></comment>
70
+ <frontend_type>select</frontend_type>
71
+ <source_model>adminhtml/system_config_source_yesno</source_model>
72
+ <sort_order>5</sort_order>
73
+ <show_in_default>1</show_in_default>
74
+ <show_in_website>1</show_in_website>
75
+ <show_in_store>1</show_in_store>
76
+ </sync_catalog>
77
+ </fields>
78
+
79
+ </account>
80
+ </groups>
81
+ </vumatch>
82
+ </sections>
83
+ </config>
84
+
app/etc/modules/Vufind_Vumatch.xml ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <config>
3
+ <modules>
4
+ <Vufind_Vumatch>
5
+ <active>true</active>
6
+ <codePool>community</codePool>
7
+ </Vufind_Vumatch>
8
+ </modules>
9
+ </config>
package.xml ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <package>
3
+ <name>Vufind_Vumatch</name>
4
+ <version>1.0.0</version>
5
+ <stability>stable</stability>
6
+ <license uri="http://opensource.org/licenses/osl-3.0.php">Open Software License</license>
7
+ <channel>community</channel>
8
+ <extends/>
9
+ <summary>Inspire shoppers with visual &amp; behavioral recommendations &amp; deliver 15% conversion lift</summary>
10
+ <description>&lt;h1&gt;vuMatch Visual Product Recommendations&lt;/h1&gt;&#xD;
11
+ &#xD;
12
+ &lt;strong&gt;DeepVu&#x2019;s vuMatch delivers visual recommendations that get smarter with usage to deliver the maximum conversion lift while insipring shoppers to find and purchase products they love.&lt;/strong&gt; &#xD;
13
+ &#xD;
14
+ &lt;h2&gt;Deep Learning for AI Commerce&lt;/h2&gt;&#xD;
15
+ DeepVu&#x2019;s deep-learning engine analyses your catalog's visual features, and your shoppers reactions to the recommendations to deliver the smartest recommendations based on visual similarity and insights on what&#x2019;s resonating with your shoppers. The result: an AI-commerce user experience for your shoppers and maximum conversion lift for the retailer. &#xD;
16
+ &#xD;
17
+ &lt;h2&gt;Conversion Lift&lt;/h2&gt;&#xD;
18
+ We commit to delivering more than 15% conversion lift quarterly or you can cancel with no further obligation!</description>
19
+ <notes>Initial stable release</notes>
20
+ <authors><author><name>DeepVu</name><user>deepvu</user><email>mr@deepvu.co</email></author></authors>
21
+ <date>2015-10-31</date>
22
+ <time>21:03:03</time>
23
+ <contents><target name="magecommunity"><dir name="Vufind"><dir name="Vumatch"><dir name="Block"><file name="Widget.php" hash="ae638e5a1feaf9c5bf71da4aa835bfb1"/></dir><dir name="Helper"><file name="Data.php" hash="e4a6f0dcc3111b3c4f7c65eefc5fe0d8"/></dir><dir name="Model"><file name="Abstract.php" hash="110211094d1bee58864e6ee4a4a723b3"/><file name="Api.php" hash="8694f4e7563477caf292994766f84807"/><file name="Observer.php" hash="44e0687341f52258feae2809234b286e"/></dir><dir name="etc"><file name="config.xml" hash="e729cc2c4deb09a9217a23cdf0cd5a7d"/><file name="system.xml" hash="8634402431fbd27f0382002adf151c93"/></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="Vufind_Vumatch.xml" hash="40f389710e714394c547090f213e5044"/></dir></target></contents>
24
+ <compatible/>
25
+ <dependencies><required><php><min>5.2.0</min><max>6.0.0</max></php></required></dependencies>
26
+ </package>