Version Notes
Please contact help@commercestack.com with any feature requests, bugs, issues, or questions.
Download this release
Release Info
Developer | CommerceStack |
Extension | CommerceStack_Recommender |
Version | 3.0.2 |
Comparing to | |
See all releases |
Code changes from version 3.0.1 to 3.0.2
- app/code/community/CommerceStack/CsApiClient/etc/config.xml +2 -2
- app/code/community/CommerceStack/Recommender/Model/Category/Indexer/Product.php +263 -0
- app/code/community/CommerceStack/Recommender/Model/Product/Indexer/Category.php +0 -124
- app/code/community/CommerceStack/Recommender/Model/Resource/Eav/Mysql4/Product/Link/Product/{Collection.php → Cl.php} +5 -1
- app/code/community/CommerceStack/Recommender/Model/Resource/Mysql4/Category/Indexer/Product.php +169 -0
- app/code/community/CommerceStack/Recommender/etc/config.xml +3 -3
- package.xml +4 -4
app/code/community/CommerceStack/CsApiClient/etc/config.xml
CHANGED
@@ -17,8 +17,8 @@
|
|
17 |
<default>
|
18 |
<csapiclient>
|
19 |
<api>
|
20 |
-
|
21 |
-
|
22 |
<create_account_uri>account/</create_account_uri>
|
23 |
</api>
|
24 |
</csapiclient>
|
17 |
<default>
|
18 |
<csapiclient>
|
19 |
<api>
|
20 |
+
<!--<base_uri>https://api.commercestack.com/</base_uri>-->
|
21 |
+
<base_uri>http://127.0.0.1/recommender/public/</base_uri>
|
22 |
<create_account_uri>account/</create_account_uri>
|
23 |
</api>
|
24 |
</csapiclient>
|
app/code/community/CommerceStack/Recommender/Model/Category/Indexer/Product.php
ADDED
@@ -0,0 +1,263 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class CommerceStack_Recommender_Model_Category_Indexer_Product extends Mage_Index_Model_Indexer_Abstract
|
4 |
+
{
|
5 |
+
/**
|
6 |
+
* Data key for matching result to be saved in
|
7 |
+
*/
|
8 |
+
const EVENT_MATCH_RESULT_KEY = 'recommender_category_product_match_result';
|
9 |
+
const EVENT_POST_RECOMMENDER_INDEX = 'after_reindex_process_commercestack_recommender';
|
10 |
+
|
11 |
+
/**
|
12 |
+
* @var array
|
13 |
+
*/
|
14 |
+
protected $_matchedEntities = array(
|
15 |
+
Mage_Catalog_Model_Product::ENTITY => array(
|
16 |
+
Mage_Index_Model_Event::TYPE_SAVE,
|
17 |
+
//Mage_Index_Model_Event::TYPE_MASS_ACTION
|
18 |
+
),
|
19 |
+
Mage_Catalog_Model_Category::ENTITY => array(
|
20 |
+
Mage_Index_Model_Event::TYPE_SAVE
|
21 |
+
),
|
22 |
+
Mage_Core_Model_Store::ENTITY => array(
|
23 |
+
Mage_Index_Model_Event::TYPE_SAVE
|
24 |
+
),
|
25 |
+
Mage_Core_Model_Store_Group::ENTITY => array(
|
26 |
+
Mage_Index_Model_Event::TYPE_SAVE
|
27 |
+
),
|
28 |
+
Mage_Catalog_Model_Convert_Adapter_Product::ENTITY => array(
|
29 |
+
Mage_Index_Model_Event::TYPE_SAVE
|
30 |
+
)
|
31 |
+
);
|
32 |
+
|
33 |
+
/**
|
34 |
+
* Initialize resource
|
35 |
+
*/
|
36 |
+
protected function _construct()
|
37 |
+
{
|
38 |
+
$this->_init('recommender/category_indexer_product');
|
39 |
+
}
|
40 |
+
|
41 |
+
/**
|
42 |
+
* Retrieve Indexer name
|
43 |
+
* @return string
|
44 |
+
*/
|
45 |
+
public function getName()
|
46 |
+
{
|
47 |
+
return 'Related Products Manager';
|
48 |
+
}
|
49 |
+
|
50 |
+
/**
|
51 |
+
* Retrieve Indexer description
|
52 |
+
* @return string
|
53 |
+
*/
|
54 |
+
public function getDescription()
|
55 |
+
{
|
56 |
+
return 'Refresh automatic related products and cross-sells';
|
57 |
+
}
|
58 |
+
|
59 |
+
/**
|
60 |
+
* match whether the reindexing should be fired
|
61 |
+
* @param Mage_Index_Model_Event $event
|
62 |
+
* @return bool
|
63 |
+
*/
|
64 |
+
public function matchEvent(Mage_Index_Model_Event $event)
|
65 |
+
{
|
66 |
+
$data = $event->getNewData();
|
67 |
+
if (isset($data[self::EVENT_MATCH_RESULT_KEY])) {
|
68 |
+
return $data[self::EVENT_MATCH_RESULT_KEY];
|
69 |
+
}
|
70 |
+
|
71 |
+
$entity = $event->getEntity();
|
72 |
+
if ($entity == Mage_Core_Model_Store::ENTITY) {
|
73 |
+
$store = $event->getDataObject();
|
74 |
+
if ($store && ($store->isObjectNew() || $store->dataHasChangedFor('group_id'))) {
|
75 |
+
$result = true;
|
76 |
+
} else {
|
77 |
+
$result = false;
|
78 |
+
}
|
79 |
+
} elseif ($entity == Mage_Core_Model_Store_Group::ENTITY) {
|
80 |
+
$storeGroup = $event->getDataObject();
|
81 |
+
$hasDataChanges = $storeGroup && ($storeGroup->dataHasChangedFor('root_category_id')
|
82 |
+
|| $storeGroup->dataHasChangedFor('website_id'));
|
83 |
+
if ($storeGroup && !$storeGroup->isObjectNew() && $hasDataChanges) {
|
84 |
+
$result = true;
|
85 |
+
} else {
|
86 |
+
$result = false;
|
87 |
+
}
|
88 |
+
} else {
|
89 |
+
$result = parent::matchEvent($event);
|
90 |
+
}
|
91 |
+
|
92 |
+
$event->addNewData(self::EVENT_MATCH_RESULT_KEY, $result);
|
93 |
+
|
94 |
+
return $result;
|
95 |
+
}
|
96 |
+
|
97 |
+
/**
|
98 |
+
* Register data required by process in event object
|
99 |
+
* Check if category ids was changed
|
100 |
+
*
|
101 |
+
* @param Mage_Index_Model_Event $event
|
102 |
+
*/
|
103 |
+
protected function _registerEvent(Mage_Index_Model_Event $event)
|
104 |
+
{
|
105 |
+
$event->addNewData(self::EVENT_MATCH_RESULT_KEY, true);
|
106 |
+
$entity = $event->getEntity();
|
107 |
+
switch ($entity)
|
108 |
+
{
|
109 |
+
case Mage_Catalog_Model_Product::ENTITY:
|
110 |
+
$this->_registerProductEvent($event);
|
111 |
+
break;
|
112 |
+
|
113 |
+
case Mage_Catalog_Model_Category::ENTITY:
|
114 |
+
$this->_registerCategoryEvent($event);
|
115 |
+
break;
|
116 |
+
}
|
117 |
+
return $this;
|
118 |
+
}
|
119 |
+
|
120 |
+
/**
|
121 |
+
* Register data required by process in event object
|
122 |
+
* @param Mage_Index_Model_Event $event
|
123 |
+
*/
|
124 |
+
// protected function _registerEvent(Mage_Index_Model_Event $event)
|
125 |
+
// {
|
126 |
+
// $event->addNewData(self::EVENT_MATCH_RESULT_KEY, true);
|
127 |
+
// $process = $event->getProcess();
|
128 |
+
//
|
129 |
+
// try
|
130 |
+
// {
|
131 |
+
// /** @var $dataHelper CommerceStack_Recommender_Helper_Data */
|
132 |
+
// $dataHelper = Mage::helper('recommender');
|
133 |
+
// $dataHelper->requestUpdate(3);
|
134 |
+
// }
|
135 |
+
// catch(Exception $e)
|
136 |
+
// {
|
137 |
+
// // Manual indexing required
|
138 |
+
// $process->changeStatus(Mage_Index_Model_Process::STATUS_REQUIRE_REINDEX);
|
139 |
+
// }
|
140 |
+
//
|
141 |
+
// return $this;
|
142 |
+
// }
|
143 |
+
|
144 |
+
/**
|
145 |
+
* Register event data during product save process
|
146 |
+
*
|
147 |
+
* @param Mage_Index_Model_Event $event
|
148 |
+
*/
|
149 |
+
protected function _registerProductEvent(Mage_Index_Model_Event $event)
|
150 |
+
{
|
151 |
+
$eventType = $event->getType();
|
152 |
+
if ($eventType == Mage_Index_Model_Event::TYPE_SAVE)
|
153 |
+
{
|
154 |
+
$product = $event->getDataObject();
|
155 |
+
/**
|
156 |
+
* Check if product categories data was changed
|
157 |
+
*/
|
158 |
+
if ($product->getIsChangedCategories())
|
159 |
+
{
|
160 |
+
$event->addNewData('category_ids', $product->getCategoryIds());
|
161 |
+
}
|
162 |
+
}
|
163 |
+
// else if ($eventType == Mage_Index_Model_Event::TYPE_MASS_ACTION) {
|
164 |
+
// /* @var $actionObject Varien_Object */
|
165 |
+
// $actionObject = $event->getDataObject();
|
166 |
+
// $attributes = array('status', 'visibility');
|
167 |
+
// $rebuildIndex = false;
|
168 |
+
//
|
169 |
+
// // check if attributes changed
|
170 |
+
// $attrData = $actionObject->getAttributesData();
|
171 |
+
// if (is_array($attrData)) {
|
172 |
+
// foreach ($attributes as $attributeCode) {
|
173 |
+
// if (array_key_exists($attributeCode, $attrData)) {
|
174 |
+
// $rebuildIndex = true;
|
175 |
+
// break;
|
176 |
+
// }
|
177 |
+
// }
|
178 |
+
// }
|
179 |
+
//
|
180 |
+
// // check changed websites
|
181 |
+
// if ($actionObject->getWebsiteIds()) {
|
182 |
+
// $rebuildIndex = true;
|
183 |
+
// }
|
184 |
+
//
|
185 |
+
// // register affected products
|
186 |
+
// if ($rebuildIndex) {
|
187 |
+
// $event->addNewData('product_ids', $actionObject->getProductIds());
|
188 |
+
// }
|
189 |
+
// }
|
190 |
+
}
|
191 |
+
|
192 |
+
/**
|
193 |
+
* Register event data during category save process
|
194 |
+
*
|
195 |
+
* @param Mage_Index_Model_Event $event
|
196 |
+
*/
|
197 |
+
protected function _registerCategoryEvent(Mage_Index_Model_Event $event)
|
198 |
+
{
|
199 |
+
$category = $event->getDataObject();
|
200 |
+
/**
|
201 |
+
* Check if product categories data was changed
|
202 |
+
*/
|
203 |
+
if ($category->getIsChangedProductList())
|
204 |
+
{
|
205 |
+
$event->addNewData('affected_product_ids', $category->getAffectedProductIds());
|
206 |
+
}
|
207 |
+
else
|
208 |
+
{
|
209 |
+
$event->addNewData('recommender_category_product_skip_call_event_handler', true);
|
210 |
+
}
|
211 |
+
/**
|
212 |
+
* Check if category has another affected category ids (category move result)
|
213 |
+
*/
|
214 |
+
// if ($category->getAffectedCategoryIds())
|
215 |
+
// {
|
216 |
+
// $event->addNewData('affected_category_ids', $category->getAffectedCategoryIds());
|
217 |
+
// }
|
218 |
+
|
219 |
+
}
|
220 |
+
|
221 |
+
/**
|
222 |
+
* Process event
|
223 |
+
* @param Mage_Index_Model_Event $event
|
224 |
+
*/
|
225 |
+
protected function _processEvent(Mage_Index_Model_Event $event)
|
226 |
+
{
|
227 |
+
$data = $event->getNewData();
|
228 |
+
if (!empty($data['recommender_category_product_reindex_all'])) {
|
229 |
+
$this->reindexAll();
|
230 |
+
}
|
231 |
+
if (empty($data['recommender_category_product_skip_call_event_handler'])) {
|
232 |
+
$this->callEventHandler($event);
|
233 |
+
}
|
234 |
+
}
|
235 |
+
|
236 |
+
|
237 |
+
/**
|
238 |
+
* Rebuild all index data
|
239 |
+
*/
|
240 |
+
public function reindexAll()
|
241 |
+
{
|
242 |
+
/** @var $dataHelper CommerceStack_Recommender_Helper_Data */
|
243 |
+
$dataHelper = Mage::helper('recommender');
|
244 |
+
$dataHelper->doClientDrivenUpdate();
|
245 |
+
}
|
246 |
+
|
247 |
+
public function setStatus($status)
|
248 |
+
{
|
249 |
+
$process = Mage::getSingleton('index/indexer')->getProcessByCode('commercestack_recommender');
|
250 |
+
switch($status)
|
251 |
+
{
|
252 |
+
case "STATUS_PENDING":
|
253 |
+
$process->changeStatus(Mage_Index_Model_Process::STATUS_PENDING);
|
254 |
+
break;
|
255 |
+
case "STATUS_RUNNING":
|
256 |
+
$process->changeStatus(Mage_Index_Model_Process::STATUS_RUNNING);
|
257 |
+
break;
|
258 |
+
case "STATUS_REQUIRE_REINDEX":
|
259 |
+
$process->changeStatus(Mage_Index_Model_Process::STATUS_REQUIRE_REINDEX);
|
260 |
+
break;
|
261 |
+
}
|
262 |
+
}
|
263 |
+
}
|
app/code/community/CommerceStack/Recommender/Model/Product/Indexer/Category.php
DELETED
@@ -1,124 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
class CommerceStack_Recommender_Model_Product_Indexer_Category extends Mage_Index_Model_Indexer_Abstract
|
4 |
-
{
|
5 |
-
/**
|
6 |
-
* Data key for matching result to be saved in
|
7 |
-
*/
|
8 |
-
const EVENT_MATCH_RESULT_KEY = 'catalog_category_product_match_result';
|
9 |
-
const EVENT_POST_RECOMMENDER_INDEX = 'after_reindex_process_commercestack_recommender';
|
10 |
-
|
11 |
-
/**
|
12 |
-
* @var array
|
13 |
-
*/
|
14 |
-
protected $_matchedEntities = array(
|
15 |
-
Mage_Catalog_Model_Product::ENTITY => array(
|
16 |
-
Mage_Index_Model_Event::TYPE_SAVE,
|
17 |
-
Mage_Index_Model_Event::TYPE_MASS_ACTION
|
18 |
-
),
|
19 |
-
Mage_Catalog_Model_Category::ENTITY => array(
|
20 |
-
Mage_Index_Model_Event::TYPE_SAVE
|
21 |
-
)
|
22 |
-
);
|
23 |
-
|
24 |
-
/**
|
25 |
-
* Retrieve Indexer name
|
26 |
-
* @return string
|
27 |
-
*/
|
28 |
-
public function getName()
|
29 |
-
{
|
30 |
-
return 'Related Products Manager';
|
31 |
-
}
|
32 |
-
|
33 |
-
/**
|
34 |
-
* Retrieve Indexer description
|
35 |
-
* @return string
|
36 |
-
*/
|
37 |
-
public function getDescription()
|
38 |
-
{
|
39 |
-
return 'Refresh automatic related products and cross-sells';
|
40 |
-
}
|
41 |
-
|
42 |
-
/**
|
43 |
-
* Register data required by process in event object
|
44 |
-
* @param Mage_Index_Model_Event $event
|
45 |
-
*/
|
46 |
-
protected function _registerEvent(Mage_Index_Model_Event $event)
|
47 |
-
{
|
48 |
-
// $event->addNewData(self::EVENT_MATCH_RESULT_KEY, true);
|
49 |
-
// $process = $event->getProcess();
|
50 |
-
//
|
51 |
-
// try
|
52 |
-
// {
|
53 |
-
// /** @var $dataHelper CommerceStack_Recommender_Helper_Data */
|
54 |
-
// $dataHelper = Mage::helper('recommender');
|
55 |
-
// $dataHelper->requestUpdate(3);
|
56 |
-
// }
|
57 |
-
// catch(Exception $e)
|
58 |
-
// {
|
59 |
-
// // Manual indexing required
|
60 |
-
// $process->changeStatus(Mage_Index_Model_Process::STATUS_REQUIRE_REINDEX);
|
61 |
-
// }
|
62 |
-
//
|
63 |
-
// return $this;
|
64 |
-
}
|
65 |
-
|
66 |
-
/**
|
67 |
-
* Process event
|
68 |
-
* @param Mage_Index_Model_Event $event
|
69 |
-
*/
|
70 |
-
protected function _processEvent(Mage_Index_Model_Event $event)
|
71 |
-
{
|
72 |
-
|
73 |
-
}
|
74 |
-
|
75 |
-
|
76 |
-
/**
|
77 |
-
* match whether the reindexing should be fired
|
78 |
-
* @param Mage_Index_Model_Event $event
|
79 |
-
* @return bool
|
80 |
-
*/
|
81 |
-
public function matchEvent(Mage_Index_Model_Event $event)
|
82 |
-
{
|
83 |
-
// $data = $event->getNewData();
|
84 |
-
// if (isset($data[self::EVENT_MATCH_RESULT_KEY])) {
|
85 |
-
// return $data[self::EVENT_MATCH_RESULT_KEY];
|
86 |
-
// }
|
87 |
-
// $entity = $event->getEntity();
|
88 |
-
// $result = true;
|
89 |
-
// if (!($entity == Mage_Catalog_Model_Product::ENTITY || $entity == Mage_Catalog_Model_Category::ENTITY))
|
90 |
-
// {
|
91 |
-
// return;
|
92 |
-
// }
|
93 |
-
// $event->addNewData(self::EVENT_MATCH_RESULT_KEY, $result);
|
94 |
-
// return $result;
|
95 |
-
}
|
96 |
-
|
97 |
-
/**
|
98 |
-
* Rebuild all index data
|
99 |
-
*/
|
100 |
-
public function reindexAll()
|
101 |
-
{
|
102 |
-
/** @var $dataHelper CommerceStack_Recommender_Helper_Data */
|
103 |
-
$dataHelper = Mage::helper('recommender');
|
104 |
-
$dataHelper->doClientDrivenUpdate();
|
105 |
-
|
106 |
-
}
|
107 |
-
|
108 |
-
public function setStatus($status)
|
109 |
-
{
|
110 |
-
$process = Mage::getSingleton('index/indexer')->getProcessByCode('commercestack_recommender');
|
111 |
-
switch($status)
|
112 |
-
{
|
113 |
-
case "STATUS_PENDING":
|
114 |
-
$process->changeStatus(Mage_Index_Model_Process::STATUS_PENDING);
|
115 |
-
break;
|
116 |
-
case "STATUS_RUNNING":
|
117 |
-
$process->changeStatus(Mage_Index_Model_Process::STATUS_RUNNING);
|
118 |
-
break;
|
119 |
-
case "STATUS_REQUIRE_REINDEX":
|
120 |
-
$process->changeStatus(Mage_Index_Model_Process::STATUS_REQUIRE_REINDEX);
|
121 |
-
break;
|
122 |
-
}
|
123 |
-
}
|
124 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
app/code/community/CommerceStack/Recommender/Model/Resource/Eav/Mysql4/Product/Link/Product/{Collection.php → Cl.php}
RENAMED
@@ -1,5 +1,9 @@
|
|
1 |
<?php
|
2 |
-
class
|
|
|
|
|
|
|
|
|
3 |
extends Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Link_Product_Collection
|
4 |
{
|
5 |
/**
|
1 |
<?php
|
2 |
+
// Changed class name to stay under 100 characters and avoid Magento Connect bug where files with paths
|
3 |
+
// over 100 characters are dropped as directories on some flavors of Linux.
|
4 |
+
|
5 |
+
//class CommerceStack_Recommender_Model_Resource_Eav_Mysql4_Product_Link_Product_Collection
|
6 |
+
class CommerceStack_Recommender_Model_Resource_Eav_Mysql4_Product_Link_Product_Cl
|
7 |
extends Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Link_Product_Collection
|
8 |
{
|
9 |
/**
|
app/code/community/CommerceStack/Recommender/Model/Resource/Mysql4/Category/Indexer/Product.php
ADDED
@@ -0,0 +1,169 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Resource model for category product indexer
|
5 |
+
*
|
6 |
+
* @category Mage
|
7 |
+
* @package Mage_Catalog
|
8 |
+
* @author Magento Core Team <core@magentocommerce.com>
|
9 |
+
*/
|
10 |
+
class CommerceStack_Recommender_Model_Resource_Mysql4_Category_Indexer_Product extends Mage_Index_Model_Resource_Abstract
|
11 |
+
{
|
12 |
+
/**
|
13 |
+
* Category table
|
14 |
+
*
|
15 |
+
* @var string
|
16 |
+
*/
|
17 |
+
protected $_categoryTable;
|
18 |
+
|
19 |
+
/**
|
20 |
+
* Category product table
|
21 |
+
*
|
22 |
+
* @var string
|
23 |
+
*/
|
24 |
+
protected $_categoryProductTable;
|
25 |
+
|
26 |
+
protected function _construct()
|
27 |
+
{
|
28 |
+
$this->_init('recommender/product_link', 'link_id');
|
29 |
+
$this->_categoryTable = $this->getTable('catalog/category');
|
30 |
+
$this->_categoryProductTable = $this->getTable('catalog/category_product');
|
31 |
+
}
|
32 |
+
|
33 |
+
public function catalogProductSave(Mage_Index_Model_Event $event)
|
34 |
+
{
|
35 |
+
$productId = $event->getEntityPk();
|
36 |
+
$data = $event->getNewData();
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Check if category ids were updated
|
40 |
+
*/
|
41 |
+
if (!isset($data['category_ids'])) {
|
42 |
+
return $this;
|
43 |
+
}
|
44 |
+
|
45 |
+
$this->_refreshProductLinks($productId);
|
46 |
+
|
47 |
+
return $this;
|
48 |
+
}
|
49 |
+
|
50 |
+
public function catalogCategorySave(Mage_Index_Model_Event $event)
|
51 |
+
{
|
52 |
+
$data = $event->getNewData();
|
53 |
+
|
54 |
+
if(!isset($data['affected_product_ids']) || count($data['affected_product_ids']) < 1)
|
55 |
+
{
|
56 |
+
return $this;
|
57 |
+
}
|
58 |
+
|
59 |
+
foreach($data['affected_product_ids'] as $productId)
|
60 |
+
{
|
61 |
+
$this->_refreshProductLinks($productId);
|
62 |
+
}
|
63 |
+
|
64 |
+
return $this;
|
65 |
+
}
|
66 |
+
|
67 |
+
protected function _refreshProductLinks($productId)
|
68 |
+
{
|
69 |
+
/**
|
70 |
+
* Select relations to categories
|
71 |
+
*/
|
72 |
+
$select = $this->_getWriteAdapter()->select()
|
73 |
+
->from(array('cp' => $this->_categoryProductTable), 'category_id')
|
74 |
+
->joinInner(array('ce' => $this->_categoryTable), 'ce.entity_id=cp.category_id', 'path')
|
75 |
+
->where('cp.product_id=:product_id');
|
76 |
+
|
77 |
+
/**
|
78 |
+
* Get information about current product categories
|
79 |
+
*/
|
80 |
+
$categories = $this->_getWriteAdapter()->fetchPairs($select, array('product_id' => $productId));
|
81 |
+
$categoryIds = array();
|
82 |
+
$allCategoryIds = array();
|
83 |
+
|
84 |
+
foreach ($categories as $id=>$path) {
|
85 |
+
$categoryIds[] = $id;
|
86 |
+
$allCategoryIds = array_merge($allCategoryIds, explode('/', $path));
|
87 |
+
}
|
88 |
+
$allCategoryIds = array_map('intval', array_unique($allCategoryIds));
|
89 |
+
//$allCategoryIds = array_map('intval', array_diff($allCategoryIds, $categoryIds));
|
90 |
+
|
91 |
+
/**
|
92 |
+
* Delete previous index data (Zend makes doing deletes on multiple OR where clauses difficult so we do two.
|
93 |
+
*/
|
94 |
+
if(count($allCategoryIds))
|
95 |
+
{
|
96 |
+
// There are some remaining or new categories so delete the links that aren't these remaining or new
|
97 |
+
// categories (that is, delete links that were just removed)
|
98 |
+
$this->_getWriteAdapter()->delete(
|
99 |
+
$this->getMainTable(),
|
100 |
+
array('product_id = ?' => $productId, 'category_id NOT IN (?)' => $allCategoryIds));
|
101 |
+
|
102 |
+
$this->_getWriteAdapter()->delete(
|
103 |
+
$this->getMainTable(),
|
104 |
+
array('linked_product_id = ?' => $productId, 'category_id NOT IN (?)' => $allCategoryIds));
|
105 |
+
}
|
106 |
+
else
|
107 |
+
{
|
108 |
+
// There are no categories left. Delete all links
|
109 |
+
$this->_getWriteAdapter()->delete(
|
110 |
+
$this->getMainTable(),
|
111 |
+
array('product_id = ?' => $productId));
|
112 |
+
|
113 |
+
$this->_getWriteAdapter()->delete(
|
114 |
+
$this->getMainTable(),
|
115 |
+
array('linked_product_id = ?' => $productId));
|
116 |
+
|
117 |
+
return $this;
|
118 |
+
}
|
119 |
+
|
120 |
+
// Identify new categories (that is, categoryIds for this product where there are no linked products)
|
121 |
+
$select = $this->_getReadAdapter()->select()->distinct()
|
122 |
+
->from($this->getMainTable(), 'category_id')
|
123 |
+
->where('product_id = ?', $productId);
|
124 |
+
|
125 |
+
$stmt = $select->query();
|
126 |
+
$result = $stmt->fetchAll();
|
127 |
+
|
128 |
+
$existingCategoryIds = array();
|
129 |
+
foreach($result as $row)
|
130 |
+
{
|
131 |
+
$existingCategoryIds[] = $row['category_id'];
|
132 |
+
}
|
133 |
+
|
134 |
+
$neededCategoryIds = array_diff($allCategoryIds, $existingCategoryIds);
|
135 |
+
|
136 |
+
foreach($neededCategoryIds as $neededCategoryId)
|
137 |
+
{
|
138 |
+
// Grab products from same categories
|
139 |
+
$neededCategoryId = (int)$neededCategoryId;
|
140 |
+
$productId = (int)$productId;
|
141 |
+
|
142 |
+
$select = $this->_getReadAdapter()->select()->distinct()
|
143 |
+
->from($this->getMainTable(), 'linked_product_id')
|
144 |
+
->where('category_id = ?', $neededCategoryId)
|
145 |
+
->limit(10);
|
146 |
+
|
147 |
+
$result = $this->_getReadAdapter()->fetchCol($select);
|
148 |
+
|
149 |
+
// Sadly, MySQL will lock if we do an INSERT INTO... SELECT above and Zend DB has no support for writing
|
150 |
+
// multiple rows so we must do n INSERTS here for each link_type_id;
|
151 |
+
$i = 1;
|
152 |
+
foreach($result as $linkedProductId)
|
153 |
+
{
|
154 |
+
$newLinkedProductRow = array(
|
155 |
+
'product_id' => $productId,
|
156 |
+
'category_id' => $neededCategoryId,
|
157 |
+
'linked_product_id' => (int)$linkedProductId,
|
158 |
+
'position' => $i++,
|
159 |
+
'link_type_id' => Mage_Catalog_Model_Product_Link::LINK_TYPE_RELATED
|
160 |
+
);
|
161 |
+
|
162 |
+
$this->_getWriteAdapter()->insert($this->getMainTable(), $newLinkedProductRow);
|
163 |
+
|
164 |
+
$newLinkedProductRow['link_type_id'] = Mage_Catalog_Model_Product_Link::LINK_TYPE_CROSSSELL;
|
165 |
+
$this->_getWriteAdapter()->insert($this->getMainTable(), $newLinkedProductRow);
|
166 |
+
}
|
167 |
+
}
|
168 |
+
}
|
169 |
+
}
|
app/code/community/CommerceStack/Recommender/etc/config.xml
CHANGED
@@ -2,7 +2,7 @@
|
|
2 |
<config>
|
3 |
<modules>
|
4 |
<CommerceStack_Recommender>
|
5 |
-
<version>3.0.
|
6 |
</CommerceStack_Recommender>
|
7 |
</modules>
|
8 |
|
@@ -38,7 +38,7 @@
|
|
38 |
<index>
|
39 |
<indexer>
|
40 |
<commercestack_recommender>
|
41 |
-
<model>recommender/
|
42 |
</commercestack_recommender>
|
43 |
</indexer>
|
44 |
</index>
|
@@ -63,7 +63,7 @@
|
|
63 |
<catalog_resource_eav_mysql4>
|
64 |
<rewrite>
|
65 |
<product_link>CommerceStack_Recommender_Model_Resource_Eav_Mysql4_Product_Link</product_link>
|
66 |
-
<product_link_product_collection>
|
67 |
</rewrite>
|
68 |
</catalog_resource_eav_mysql4>
|
69 |
</models>
|
2 |
<config>
|
3 |
<modules>
|
4 |
<CommerceStack_Recommender>
|
5 |
+
<version>3.0.2</version>
|
6 |
</CommerceStack_Recommender>
|
7 |
</modules>
|
8 |
|
38 |
<index>
|
39 |
<indexer>
|
40 |
<commercestack_recommender>
|
41 |
+
<model>recommender/category_indexer_product</model>
|
42 |
</commercestack_recommender>
|
43 |
</indexer>
|
44 |
</index>
|
63 |
<catalog_resource_eav_mysql4>
|
64 |
<rewrite>
|
65 |
<product_link>CommerceStack_Recommender_Model_Resource_Eav_Mysql4_Product_Link</product_link>
|
66 |
+
<product_link_product_collection>CommerceStack_Recommender_Model_Resource_Eav_Mysql4_Product_Link_Product_Cl</product_link_product_collection>
|
67 |
</rewrite>
|
68 |
</catalog_resource_eav_mysql4>
|
69 |
</models>
|
package.xml
CHANGED
@@ -1,7 +1,7 @@
|
|
1 |
<?xml version="1.0"?>
|
2 |
<package>
|
3 |
<name>CommerceStack_Recommender</name>
|
4 |
-
<version>3.0.
|
5 |
<stability>stable</stability>
|
6 |
<license uri="http://opensource.org/licenses/osl-3.0.php">Open Software License v 3.0</license>
|
7 |
<channel>community</channel>
|
@@ -16,9 +16,9 @@ Please contact help@commercestack.com with any bugs, issues, or feature requests
|
|
16 |
After installing, navigate to System->Configuration->Related Products Manager to begin.</description>
|
17 |
<notes>Please contact help@commercestack.com with any feature requests, bugs, issues, or questions.</notes>
|
18 |
<authors><author><name>CommerceStack</name><user>dbright</user><email>dbright@commercestack.com</email></author></authors>
|
19 |
-
<date>2015-11-
|
20 |
-
<time>
|
21 |
-
<contents><target name="magecommunity"><dir name="CommerceStack"><dir name="Recommender"><dir name="Block"><dir name="Cart"><file name="Crosssell.php" hash="e97eb9a5f718b3c549372388739075b2"/></dir><dir name="Catalog"><dir name="Product"><dir name="Edit"><dir name="Tab"><file name="Crosssell.php" hash="4a629f55e16abcd45d8b97ea7b83ee9d"/><file name="Related.php" hash="5d3e6e6fbeadee6a7b5b31675338171e"/></dir><file name="Tabs.php" hash="7e03bf328aee99fa9d591dc3836ee6d3"/></dir></dir></dir><dir name="Product"><dir name="List"><file name="Related.php" hash="7a80f10945bd246f0d907fa016459124"/><file name="Upsell.php" hash="3142af81e5978ef1814fd334ab66e85c"/></dir></dir><dir name="System"><dir name="Config"><dir name="Form"><file name="Apikey.php" hash="def235a2710cea0b01ace89bce9ffda4"/><file name="Apikeyurl.php" hash="5ce3031fd84f912b3552d7c37f2a04ac"/><file name="Apisecret.php" hash="9b9a92981a5ff80aa4ec3e4255844801"/><file name="Apiuser.php" hash="bba5a87192ab0821d999aa4ab8cddada"/><file name="Cancelbutton.php" hash="7a87871461a6d589a28ccbc18f9d1603"/><file name="Customrulesiframe.php" hash="523b3dd848d62ab31bdc285ec2b6fdbb"/><file name="Email.php" hash="0231900a317a75e1f72cfdd440df2e45"/><file name="Helpiframe.php" hash="cd049db20bfa53e6a57eaba796a0f5b6"/><file name="Paymentiframe.php" hash="d69c5e5af421dc15bc2f27d871af20be"/><file name="Updatebutton.php" hash="5171684960b8e5b9030bd4f0bc427234"/></dir><file name="Form.php" hash="e879294fa8ff2d914dbe352979a2cc0e"/></dir></dir></dir><dir name="Helper"><file name="Data.php" hash="dd7921ec7598a4abbd643b833dd10909"/></dir><dir name="Model"><dir name="
|
22 |
<compatible/>
|
23 |
<dependencies><required><php><min>5.2.13</min><max>6.0.0</max></php></required></dependencies>
|
24 |
</package>
|
1 |
<?xml version="1.0"?>
|
2 |
<package>
|
3 |
<name>CommerceStack_Recommender</name>
|
4 |
+
<version>3.0.2</version>
|
5 |
<stability>stable</stability>
|
6 |
<license uri="http://opensource.org/licenses/osl-3.0.php">Open Software License v 3.0</license>
|
7 |
<channel>community</channel>
|
16 |
After installing, navigate to System->Configuration->Related Products Manager to begin.</description>
|
17 |
<notes>Please contact help@commercestack.com with any feature requests, bugs, issues, or questions.</notes>
|
18 |
<authors><author><name>CommerceStack</name><user>dbright</user><email>dbright@commercestack.com</email></author></authors>
|
19 |
+
<date>2015-11-24</date>
|
20 |
+
<time>16:24:46</time>
|
21 |
+
<contents><target name="magecommunity"><dir name="CommerceStack"><dir name="Recommender"><dir name="Block"><dir name="Cart"><file name="Crosssell.php" hash="e97eb9a5f718b3c549372388739075b2"/></dir><dir name="Catalog"><dir name="Product"><dir name="Edit"><dir name="Tab"><file name="Crosssell.php" hash="4a629f55e16abcd45d8b97ea7b83ee9d"/><file name="Related.php" hash="5d3e6e6fbeadee6a7b5b31675338171e"/></dir><file name="Tabs.php" hash="7e03bf328aee99fa9d591dc3836ee6d3"/></dir></dir></dir><dir name="Product"><dir name="List"><file name="Related.php" hash="7a80f10945bd246f0d907fa016459124"/><file name="Upsell.php" hash="3142af81e5978ef1814fd334ab66e85c"/></dir></dir><dir name="System"><dir name="Config"><dir name="Form"><file name="Apikey.php" hash="def235a2710cea0b01ace89bce9ffda4"/><file name="Apikeyurl.php" hash="5ce3031fd84f912b3552d7c37f2a04ac"/><file name="Apisecret.php" hash="9b9a92981a5ff80aa4ec3e4255844801"/><file name="Apiuser.php" hash="bba5a87192ab0821d999aa4ab8cddada"/><file name="Cancelbutton.php" hash="7a87871461a6d589a28ccbc18f9d1603"/><file name="Customrulesiframe.php" hash="523b3dd848d62ab31bdc285ec2b6fdbb"/><file name="Email.php" hash="0231900a317a75e1f72cfdd440df2e45"/><file name="Helpiframe.php" hash="cd049db20bfa53e6a57eaba796a0f5b6"/><file name="Paymentiframe.php" hash="d69c5e5af421dc15bc2f27d871af20be"/><file name="Updatebutton.php" hash="5171684960b8e5b9030bd4f0bc427234"/></dir><file name="Form.php" hash="e879294fa8ff2d914dbe352979a2cc0e"/></dir></dir></dir><dir name="Helper"><file name="Data.php" hash="dd7921ec7598a4abbd643b833dd10909"/></dir><dir name="Model"><dir name="Category"><dir name="Indexer"><file name="Product.php" hash="0b75655cb3bc3a7bd9a3ba66b5452249"/></dir></dir><dir name="Product"><file name="Link.php" hash="c4e15d853882690db3574424b5e275c7"/></dir><dir name="Resource"><dir name="Eav"><dir name="Mysql4"><dir name="Product"><dir name="Link"><dir name="Product"><file name="Cl.php" hash="64f7e356d20d76257ceb1334e6ec1036"/></dir><file name=".DS_Store" hash="94881651f077db217b9ec427591b721c"/></dir><file name="Link.php" hash="80fa3f20b8a3894bab960e01c4e052f5"/><file name=".DS_Store" hash="e999693fd37d82450997699da2d986e2"/></dir><file name=".DS_Store" hash="d032518ab85e6c3cbbb43688f6bc5bfe"/></dir><file name=".DS_Store" hash="4c2b2d46eba62dd07c7ffc1cf30460b4"/></dir><dir name="Mysql4"><dir name="Category"><dir name="Indexer"><file name="Product.php" hash="bfe2a939d0ad10d7513dd21362b10663"/></dir></dir><file name="Setup.php" hash="1e93566c0f56cc52cdf4e4a73153d2f9"/></dir><file name=".DS_Store" hash="195fa1ec4bb1126dc072b289fb841603"/></dir><dir name="System"><dir name="Config"><dir name="Form"><file name="Upsellsource.php" hash="34ed5e3c61bd288340b7de3809953ad3"/></dir></dir></dir><file name=".DS_Store" hash="b98ec272e7b775e485af3b5db7b24e6c"/></dir><dir name="controllers"><file name="AccountController.php" hash="2ba2f4ae67df9a140ed2b8b5bc4ec986"/><dir name="Adminhtml"><file name="RecommenderproductController.php" hash="f106f5fce36166b0d43cbf513b234482"/></dir><file name="IndexController.php" hash="7f2b74585f445f982064de464f07e7ff"/></dir><dir name="etc"><file name="config.xml" hash="e1683feb4ec9a45e438ee84e74b92291"/><file name="system.xml" hash="83689275798fbc63b25d76a8c9191016"/></dir><dir name="sql"><dir name="recommender_setup"><file name="mysql4-install-0.9.3.php" hash="4ce1a6cfbc0dbcb55433d31d539d8f50"/><file name="mysql4-upgrade-0.9.3-0.9.4.php" hash="3beefb00777a6bd04265b7d33c23efa9"/><file name="mysql4-upgrade-0.9.4-0.9.5.php" hash="3beefb00777a6bd04265b7d33c23efa9"/><file name="mysql4-upgrade-0.9.5-1.0.0.php" hash="3beefb00777a6bd04265b7d33c23efa9"/><file name="mysql4-upgrade-1.0.0-1.0.1.php" hash="3beefb00777a6bd04265b7d33c23efa9"/><file name="mysql4-upgrade-1.0.1-1.0.2.php" hash="3beefb00777a6bd04265b7d33c23efa9"/><file name="mysql4-upgrade-1.0.2-1.1.0.php" hash="3beefb00777a6bd04265b7d33c23efa9"/><file name="mysql4-upgrade-1.1.0-1.2.0.php" hash="3beefb00777a6bd04265b7d33c23efa9"/><file name="mysql4-upgrade-1.2.0-1.2.1.php" hash="3beefb00777a6bd04265b7d33c23efa9"/><file name="mysql4-upgrade-1.2.1-1.2.2.php" hash="3beefb00777a6bd04265b7d33c23efa9"/><file name="mysql4-upgrade-1.2.2-1.2.3.php" hash="3beefb00777a6bd04265b7d33c23efa9"/><file name="mysql4-upgrade-1.2.3-1.2.4.php" hash="3beefb00777a6bd04265b7d33c23efa9"/><file name="mysql4-upgrade-1.2.4-1.2.5.php" hash="3beefb00777a6bd04265b7d33c23efa9"/><file name="mysql4-upgrade-1.2.5-1.2.6.php" hash="3beefb00777a6bd04265b7d33c23efa9"/><file name="mysql4-upgrade-1.2.6-2.0.0.php" hash="b2d2b463578d50b2a1a313c36d02ecdf"/><file name="mysql4-upgrade-2.0.0-2.0.1.php" hash="feabe5cc691b088d6ade3e04d6b120fc"/><file name="mysql4-upgrade-2.0.1-2.0.2.php" hash="feabe5cc691b088d6ade3e04d6b120fc"/><file name="mysql4-upgrade-2.0.2-2.0.3.php" hash="feabe5cc691b088d6ade3e04d6b120fc"/><file name="mysql4-upgrade-2.0.3-2.0.4.php" hash="feabe5cc691b088d6ade3e04d6b120fc"/><file name="mysql4-upgrade-2.0.4-2.0.5.php" hash="feabe5cc691b088d6ade3e04d6b120fc"/><file name="mysql4-upgrade-2.0.5-2.0.6.php" hash="feabe5cc691b088d6ade3e04d6b120fc"/><file name="mysql4-upgrade-2.0.6-2.0.7.php" hash="feabe5cc691b088d6ade3e04d6b120fc"/><file name="mysql4-upgrade-2.0.7-2.0.8.php" hash="feabe5cc691b088d6ade3e04d6b120fc"/><file name="mysql4-upgrade-2.0.8-2.0.9.php" hash="feabe5cc691b088d6ade3e04d6b120fc"/><file name="mysql4-upgrade-2.0.9-2.1.0.php" hash="feabe5cc691b088d6ade3e04d6b120fc"/><file name="mysql4-upgrade-2.1.0-2.1.1.php" hash="feabe5cc691b088d6ade3e04d6b120fc"/><file name="mysql4-upgrade-2.1.1-2.1.2.php" hash="feabe5cc691b088d6ade3e04d6b120fc"/><file name="mysql4-upgrade-2.1.2-2.1.3.php" hash="feabe5cc691b088d6ade3e04d6b120fc"/><file name="mysql4-upgrade-2.1.3-2.2.0.php" hash="feabe5cc691b088d6ade3e04d6b120fc"/><file name="mysql4-upgrade-2.2.0-2.2.1.php" hash="feabe5cc691b088d6ade3e04d6b120fc"/><file name="mysql4-upgrade-2.2.1-2.2.2.php" hash="feabe5cc691b088d6ade3e04d6b120fc"/><file name="mysql4-upgrade-2.2.2-2.2.3.php" hash="feabe5cc691b088d6ade3e04d6b120fc"/><file name="mysql4-upgrade-2.2.3-2.2.4.php" hash="feabe5cc691b088d6ade3e04d6b120fc"/><file name="mysql4-upgrade-2.2.4-3.0.0.php" hash="a73eaea333687fbf06a789fa5ca60c3c"/></dir></dir><file name=".DS_Store" hash="9567c71fb3193ad25155b1c371035ddf"/></dir><dir name="CsApiClient"><dir name="Model"><file name="Account.php" hash="20e1e6ba30fec17b4222ee962fb45285"/><file name="Server.php" hash="026be03911b4af5079f2644f06634aa5"/></dir><dir name="etc"><file name="config.xml" hash="ab61f8dc01e64d5b04a1f5d2e921f28d"/></dir></dir><dir name="CsNotification"><dir name="Model"><dir name="AdminNotification"><file name="Feed.php" hash="b394ec8eb1473b3dadef23bf5aa3c1d6"/></dir></dir><dir name="etc"><file name="config.xml" hash="9ede9a59b2e857828a341bbf53953abe"/></dir></dir></dir></target><target name="magedesign"><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="layout"><file name="recommender.xml" hash="8a42112390c712a8085f1b966c5fe437"/></dir></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="CommerceStack_Recommender.xml" hash="c0faaf57bb93c70fe6ba45e68c96fc11"/><file name="CommerceStack_CsApiClient.xml" hash="dd56312764a58b18b7e21738ebb8a6b0"/><file name="CommerceStack_CsNotification.xml" hash="94bb10db3af629c7e68bbf32fd18159c"/></dir></target></contents>
|
22 |
<compatible/>
|
23 |
<dependencies><required><php><min>5.2.13</min><max>6.0.0</max></php></required></dependencies>
|
24 |
</package>
|