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 +96 -0
- app/code/community/Vufind/Vumatch/Helper/Data.php +35 -0
- app/code/community/Vufind/Vumatch/Model/Abstract.php +99 -0
- app/code/community/Vufind/Vumatch/Model/Api.php +79 -0
- app/code/community/Vufind/Vumatch/Model/Observer.php +269 -0
- app/code/community/Vufind/Vumatch/etc/config.xml +93 -0
- app/code/community/Vufind/Vumatch/etc/system.xml +84 -0
- app/etc/modules/Vufind_Vumatch.xml +9 -0
- package.xml +26 -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> ';
|
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 & behavioral recommendations & deliver 15% conversion lift</summary>
|
10 |
+
<description><h1>vuMatch Visual Product Recommendations</h1>
|
11 |
+

|
12 |
+
<strong>DeepVu’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.</strong> 
|
13 |
+

|
14 |
+
<h2>Deep Learning for AI Commerce</h2>
|
15 |
+
DeepVu’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’s resonating with your shoppers. The result: an AI-commerce user experience for your shoppers and maximum conversion lift for the retailer. 
|
16 |
+

|
17 |
+
<h2>Conversion Lift</h2>
|
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>
|