Lumidatum_ProdRecWidget - Version 1.0.2

Version Notes

Fixing content packaging.

Download this release

Release Info

Developer Matt Lee
Extension Lumidatum_ProdRecWidget
Version 1.0.2
Comparing to
See all releases


Code changes from version 1.0.1 to 1.0.2

app/code/community/Lumidatum/ProdRecWidget/Block/Recs.php ADDED
@@ -0,0 +1,180 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Lumidatum_ProdRecWidget_Block_Recs extends Mage_Core_Block_Abstract implements Mage_Widget_Block_Interface
4
+ {
5
+ protected function _toHtml()
6
+ {
7
+ Mage::log('Starting Lumidatum Product Recommender widget processing', null, 'lumidatum-productrecommender.log');
8
+ $html = '<ol class="products-grid">';
9
+ $includedProductIds = array();
10
+ $currentStore = Mage::app()->getStore();
11
+
12
+ $lumidatumProdRecImageSize = Mage::getStoreConfig(
13
+ 'lumidatum/prodrecwidget_group/lumidatum_prodrecimagesize',
14
+ $currentStore
15
+ );
16
+
17
+ // Get product Id if on a product detail page
18
+ $currentProduct = Mage::registry('current_product');
19
+ if($currentProduct)
20
+ {
21
+ $productId = $currentProduct->getId();
22
+ Mage::log("Product view, product Id: {$productId}", null, 'lumidatum-productrecommender.log');
23
+
24
+ // Add current product Id to included product Ids (as int, not string)
25
+ array_push($includedProductIds, (int) $productId);
26
+ }
27
+
28
+ // Get user Id, if user is logged in
29
+ $customerId = Mage::getSingleton('customer/session')->getCustomer()->getId();
30
+ if($customerId)
31
+ {
32
+ Mage::log("Customer Id: {$customerId}", null, 'lumidatum-productrecommender.log');
33
+
34
+ // Get customer history and add product Ids to included product Ids
35
+ $orders= Mage::getModel('sales/order')->getCollection()->addAttributeToFilter('customer_id', $customerId);
36
+ foreach($orders as $collectionOrder)
37
+ {
38
+ $order = Mage::getModel('sales/order')->load($collectionOrder->getId());
39
+ $items = $order->getAllVisibleItems();
40
+ foreach($items as $item)
41
+ {
42
+ array_push($includedProductIds, (int) $item->getProductId());
43
+ }
44
+ }
45
+ }
46
+
47
+ // If included product ids is not empty, make an API call to Lumidatum
48
+ if($includedProductIds)
49
+ {
50
+ $recommendationProductArrays = $this->getProductRecommendations($currentStore, $customerId, $includedProductIds);
51
+ $recommendationProductIds = array_map(function($recommendationProductArray) { return $recommendationProductArray[0]; }, $recommendationProductArrays);
52
+
53
+ $recommendedProducts = Mage::getModel('catalog/product')
54
+ ->getCollection()
55
+ ->addAttributeToSelect('name')
56
+ ->addAttributeToSelect('price')
57
+ ->addAttributeToSelect('small_image')
58
+ ->addAttributeToFilter('entity_id', $recommendationProductIds)
59
+ ->load();
60
+
61
+ $i = 0;
62
+
63
+ foreach($recommendedProducts as $recommendedProduct)
64
+ {
65
+ // TODO: figure out how to use a template instead
66
+ $itemLast = (++$i == count($recommendedProducts))?' last':'';
67
+ $productId = $recommendedProduct->getId();
68
+ $productUrl = $recommendedProduct->getProductUrl();
69
+ $productName = $recommendedProduct->getName();
70
+ $productTitle = $this->stripTags($recommendedProduct->getName(), null, true);
71
+ $productImgSrc = Mage::helper('catalog/image')->init($recommendedProduct, 'small_image')->resize($lumidatumProdRecImageSize);
72
+ $productImgSrcAlt = $this->stripTags($recommendedProduct->getName(), null, true);
73
+ $productPrice = number_format($recommendedProduct->getPrice(), 2);
74
+
75
+ $html .= "<li class=\"item{$itemLast}\">";
76
+
77
+ // Product image with link
78
+ $html .= "<a href=\"{$productUrl}\" title=\"{$productTitle}\" class=\"product-image\" style=\"width:{$lumidatumProdRecImageSize}px; height:{$lumidatumProdRecImageSize}px;\"><img src=\"{$productImgSrc}\" width=\"{$lumidatumProdRecImageSize}px\" height=\"{$lumidatumProdRecImageSize}px\" alt=\"{$productImgSrcAlt}\" /></a>";
79
+
80
+ // Product name with link
81
+ $html .= "<h3 class=\"product-name\"><a href=\"{$productUrl}\" title=\"{$productTitle}\">{$productName}</a></h3>";
82
+
83
+ // Price
84
+ $html .= "<div class=\"price-box\"><span class=\"regular-price\" id=\"product-price-{$productId}\"><span class=\"price\">\${$productPrice}</span></span></div>";
85
+
86
+ $html .= "</li>";
87
+ }
88
+ }
89
+ else
90
+ {
91
+ Mage::log("Included product Ids empty", null, 'lumidatum-productrecommender.log');
92
+ }
93
+
94
+ $html .= '</ol>';
95
+
96
+ return $html;
97
+ }
98
+
99
+ public function getProductRecommendations($currentStore, $customerId, array $includedProductIds)
100
+ {
101
+ if(!$customerId)
102
+ {
103
+ $customerId = 'User not logged in';
104
+ }
105
+ $includedProductIdsString = implode($includedProductIds, ',');
106
+ Mage::log(
107
+ "Product Ids: {$includedProductIdsString}, Customer Id: {$customerId}",
108
+ null,
109
+ 'lumidatum-productrecommender.log'
110
+ );
111
+
112
+ $lumidatumRestApiBaseUrl = 'https://www.lumidatum.com/api/predict';
113
+
114
+ // Get from API Credentials from configuration set in Admin dashboard
115
+ $lumidatumModelId = Mage::getStoreConfig(
116
+ 'lumidatum/prodrecwidget_group/lumidatum_modelid',
117
+ $currentStore
118
+ );
119
+ $lumidatumApiKey = Mage::getStoreConfig(
120
+ 'lumidatum/prodrecwidget_group/lumidatum_apikey',
121
+ $currentStore
122
+ );
123
+ $lumidatumProdRecCount = Mage::getStoreConfig(
124
+ 'lumidatum/prodrecwidget_group/lumidatum_prodreccount',
125
+ $currentStore
126
+ );
127
+
128
+ Mage::log(
129
+ "Model Id: {$lumidatumModelId}, Authorization: {$lumidatumApiKey}, Url: {$lumidatumRestApiBaseUrl}/{$lumidatumModelId}",
130
+ null,
131
+ 'lumidatum-productrecommender.log'
132
+ );
133
+
134
+ if($lumidatumModelId and $lumidatumApiKey)
135
+ {
136
+ $client = new Varien_Http_Client("{$lumidatumRestApiBaseUrl}/{$lumidatumModelId}");
137
+ $client->setMethod(Varien_Http_Client::POST);
138
+ $client->setHeaders('Authorization', $lumidatumApiKey);
139
+ $client->setHeaders('Content-Type', 'application/json');
140
+
141
+ $data = array(
142
+ 'customer_id' => $customerId,
143
+ 'inc_prod_ids' => $includedProductIds,
144
+ 'exc_prod_ids' => $includedProductIds,
145
+ 'num_of_recs' => (int) $lumidatumProdRecCount,
146
+ );
147
+ $json = json_encode($data);
148
+
149
+ Mage::log("JSON payload: {$json}", null, 'lumidatum-productrecommender.log');
150
+
151
+ // TODO: add guard/http external failure handling... to not take down magento site on call failure...
152
+ $response = $client->setRawData($json)->request('POST');
153
+ if ($response->isSuccessful())
154
+ {
155
+ $responseBody = $response->getBody();
156
+ $recommendations = json_decode($responseBody)->recommendations;
157
+
158
+ Mage::log("Response body: {$responseBody}", null, 'lumidatum-productrecommender.log');
159
+
160
+ // TODO: decide whether or noto dispatch an event after receiving recommendations
161
+ // Mage::dispatchEvent('lumidatum_product_recommendation', array('recommendations' => $recommendations));
162
+ return $recommendations;
163
+ }
164
+ else
165
+ {
166
+ Mage::log(
167
+ 'Response error: ' . $response->getStatus() . ' ' . $response->getMessage(),
168
+ null,
169
+ 'lumidatum-productrecommender.log'
170
+ );
171
+ }
172
+ }
173
+ else
174
+ {
175
+ Mage::log('API call not made: missing model Id or API token', null, 'lumidatum-productrecommender.log');
176
+ }
177
+
178
+ return array();
179
+ }
180
+ }
app/code/community/Lumidatum/ProdRecWidget/Helper/Data.php ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
1
+ <?php
2
+
3
+ class Lumidatum_ProdRecWidget_Helper_Data extends Mage_Core_Helper_Abstract
4
+ {
5
+ }
app/code/community/Lumidatum/ProdRecWidget/Model/Options.php ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Lumidatum_ProdRecWidget_Model_Options
4
+ {
5
+ public function toOptionArray()
6
+ {
7
+ return array(
8
+ array('value' => '1', 'label' => 'Yes'),
9
+ array('value' => '0', 'label' => 'No'),
10
+ );
11
+ }
12
+ }
app/code/community/Lumidatum/ProdRecWidget/etc/adminhtml.xml ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <config>
3
+ <acl>
4
+ <resources>
5
+ <admin>
6
+ <children>
7
+ <system>
8
+ <children>
9
+ <config>
10
+ <children>
11
+ <lumidatum translate="title" module="lumidatum_prodrecwidget">
12
+ <title>lumidatum</title>
13
+ <sort_order>1</sort_order>
14
+ </lumidatum>
15
+ </children>
16
+ </config>
17
+ </children>
18
+ </system>
19
+ </children>
20
+ </admin>
21
+ </resources>
22
+ </acl>
23
+ </config>
app/code/community/Lumidatum/ProdRecWidget/etc/config.xml ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <config>
3
+ <modules>
4
+ <Lumidatum_ProdRecWidget>
5
+ <version>1.0.0</version>
6
+ </Lumidatum_ProdRecWidget>
7
+ </modules>
8
+ <global>
9
+ <blocks>
10
+ <lumidatum_prodrecwidget>
11
+ <class>Lumidatum_ProdRecWidget_Block</class>
12
+ </lumidatum_prodrecwidget>
13
+ </blocks>
14
+ <helpers>
15
+ <lumidatum_prodrecwidget>
16
+ <class>Lumidatum_ProdRecWidget_Helper</class>
17
+ </lumidatum_prodrecwidget>
18
+ </helpers>
19
+ </global>
20
+ <default>
21
+ <lumidatum>
22
+ <prodrecwidget_group>
23
+ <lumidatum_prodreccount>3</lumidatum_prodreccount>
24
+ <lumidatum_prodrecimagesize>85</lumidatum_prodrecimagesize>
25
+ </prodrecwidget_group>
26
+ </lumidatum>
27
+ </default>
28
+ </config>
app/code/community/Lumidatum/ProdRecWidget/etc/system.xml ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <config>
3
+ <tabs>
4
+ <lumidatum translate="label" module="lumidatum_prodrecwidget">
5
+ <label>Lumidatum Extensions</label>
6
+ </lumidatum>
7
+ </tabs>
8
+ <sections>
9
+ <lumidatum translate="label" module="lumidatum_prodrecwidget">
10
+ <label>Product Recommendation Widget Configuration</label>
11
+ <tab>lumidatum</tab>
12
+ <show_in_default>1</show_in_default>
13
+ <show_in_website>1</show_in_website>
14
+ <show_in_store>1</show_in_store>
15
+
16
+ <groups>
17
+ <prodrecwidget_group translate="label" module="lumidatum_prodrecwidget">
18
+ <label>Settings</label>
19
+ <frontend_type>text</frontend_type>
20
+ <show_in_default>1</show_in_default>
21
+ <show_in_website>1</show_in_website>
22
+ <show_in_store>1</show_in_store>
23
+
24
+ <fields>
25
+ <lumidatum_modelid translate="label">
26
+ <label>Model Id: </label>
27
+ <comment>The Id for your Lumidatum ALS model.</comment>
28
+ <sort_order>1</sort_order>
29
+ <frontend_type>text</frontend_type>
30
+ <show_in_default>1</show_in_default>
31
+ <show_in_website>1</show_in_website>
32
+ <show_in_store>1</show_in_store>
33
+ </lumidatum_modelid>
34
+ <lumidatum_apikey translate="label">
35
+ <label>API Key: </label>
36
+ <comment>The authorization token for your Lumidatum user.</comment>
37
+ <sort_order>2</sort_order>
38
+ <frontend_type>text</frontend_type>
39
+ <show_in_default>1</show_in_default>
40
+ <show_in_website>1</show_in_website>
41
+ <show_in_store>1</show_in_store>
42
+ </lumidatum_apikey>
43
+ <lumidatum_prodreccount translate="label">
44
+ <label>Recommendation count: </label>
45
+ <comment>The number of top product recommendations the API will return.</comment>
46
+ <sort_order>3</sort_order>
47
+ <frontend_type>text</frontend_type>
48
+ <show_in_default>1</show_in_default>
49
+ <show_in_website>1</show_in_website>
50
+ <show_in_store>1</show_in_store>
51
+ </lumidatum_prodreccount>
52
+ <lumidatum_prodrecimagesize translate="label">
53
+ <label>Image size: </label>
54
+ <comment>The side length in pixels of displayed product recommendation images (images are sized to fit in squares).</comment>
55
+ <sort_order>4</sort_order>
56
+ <frontend_type>text</frontend_type>
57
+ <show_in_default>1</show_in_default>
58
+ <show_in_website>1</show_in_website>
59
+ <show_in_store>1</show_in_store>
60
+ </lumidatum_prodrecimagesize>
61
+ </fields>
62
+ </prodrecwidget_group>
63
+ </groups>
64
+ </lumidatum>
65
+ </sections>
66
+ </config>
app/code/community/Lumidatum/ProdRecWidget/etc/widget.xml ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <widgets>
3
+ <lumidatum_prodrecwidget_recs type="lumidatum_prodrecwidget/recs">
4
+ <name>Lumidatum Product Recommendation Widget</name>
5
+ <description type="desc">Display the top recommendations for a given product.</description>
6
+ </lumidatum_prodrecwidget_recs>
7
+ </widgets>
app/etc/modules/Lumidatum_ProdRecWidget.xml ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <config>
3
+ <modules>
4
+ <Lumidatum_ProdRecWidget>
5
+ <active>true</active>
6
+ <codePool>community</codePool>
7
+ </Lumidatum_ProdRecWidget>
8
+ </modules>
9
+ </config>
package.xml CHANGED
@@ -1,18 +1,18 @@
1
  <?xml version="1.0"?>
2
  <package>
3
  <name>Lumidatum_ProdRecWidget</name>
4
- <version>1.0.1</version>
5
  <stability>alpha</stability>
6
  <license uri="https://opensource.org/licenses/mit-license.php">MITL</license>
7
  <channel>community</channel>
8
  <extends/>
9
  <summary>A widget that displays product recommendations from Lumidatum.</summary>
10
  <description>If you have a trained product recommendation model for Lumidatum, you can simply add this widget to your Magento site and display product recommendations for a given product being viewed, and additionally, user purchase history (if they're logged in). Simply specify your Lumidatum model Id and your Lumidatum user API token, the pages you would like the recommendation widget to appear on, and you're ready to go!</description>
11
- <notes>PHP required version adjustment.</notes>
12
  <authors><author><name>Matt Lee</name><user>Lumidatum</user><email>hello@lumidatum.com</email></author></authors>
13
  <date>2016-05-13</date>
14
- <time>19:35:01</time>
15
- <contents><target name="mageetc"><dir><dir name="var"><dir name="www"><dir name="magento.loc"><dir name="public"><dir name="magento1"><dir name="app"><file name="etc" hash=""/></dir></dir></dir></dir></dir></dir></dir></target></contents>
16
  <compatible/>
17
  <dependencies><required><php><min>5.0.0</min><max>5.6.35</max></php></required></dependencies>
18
  </package>
1
  <?xml version="1.0"?>
2
  <package>
3
  <name>Lumidatum_ProdRecWidget</name>
4
+ <version>1.0.2</version>
5
  <stability>alpha</stability>
6
  <license uri="https://opensource.org/licenses/mit-license.php">MITL</license>
7
  <channel>community</channel>
8
  <extends/>
9
  <summary>A widget that displays product recommendations from Lumidatum.</summary>
10
  <description>If you have a trained product recommendation model for Lumidatum, you can simply add this widget to your Magento site and display product recommendations for a given product being viewed, and additionally, user purchase history (if they're logged in). Simply specify your Lumidatum model Id and your Lumidatum user API token, the pages you would like the recommendation widget to appear on, and you're ready to go!</description>
11
+ <notes>Fixing content packaging.</notes>
12
  <authors><author><name>Matt Lee</name><user>Lumidatum</user><email>hello@lumidatum.com</email></author></authors>
13
  <date>2016-05-13</date>
14
+ <time>20:59:49</time>
15
+ <contents><target name="mageetc"><dir name="modules"><file name="Lumidatum_ProdRecWidget.xml" hash="ac34b1247015d5bd3d6d6d1e71b33107"/></dir></target><target name="magecommunity"><dir name="Lumidatum"><dir name="ProdRecWidget"><dir name="Block"><file name="Recs.php" hash="cca4c23bf75d1cc3df6076975be907f1"/></dir><dir name="Helper"><file name="Data.php" hash="ecc9b701fe7375c9d827aea34ba20d91"/></dir><dir name="Model"><file name="Options.php" hash="2e927161b5a725a4d81e151f9133be0f"/></dir><dir name="etc"><file name="adminhtml.xml" hash="9c81bca6786c91afe8f9abc346aa31c6"/><file name="config.xml" hash="50b1754f2763e2d269cc2005278ce9e3"/><file name="system.xml" hash="2ca24893f9e08a97c393cfcbbe9b9944"/><file name="widget.xml" hash="c22e31f52526ce118326000f985f1003"/></dir></dir></dir></target></contents>
16
  <compatible/>
17
  <dependencies><required><php><min>5.0.0</min><max>5.6.35</max></php></required></dependencies>
18
  </package>