roihunter_easy - Version 1.1.0

Version Notes

Created 16th April, 2017 Compatibility: 1.9.2.4 - CSV Product feed for Adwords compatibility, Conversion tracking, Product feed images and sale price improvements

Download this release

Release Info

Developer ROI Hunter
Extension roihunter_easy
Version 1.1.0
Comparing to
See all releases


Code changes from version 1.0.9 to 1.1.0

app/code/community/Businessfactory/Roihuntereasy/Block/Adminhtml/Admin.php CHANGED
@@ -13,6 +13,29 @@ class Businessfactory_Roihuntereasy_Block_Adminhtml_Admin extends Mage_Adminhtml
13
  return Mage::getIsDeveloperMode() ? "developer" : "production";
14
  }
15
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
  public function getDefaultStoreId()
17
  {
18
  return Mage::app()
13
  return Mage::getIsDeveloperMode() ? "developer" : "production";
14
  }
15
 
16
+ public function isStagingActive()
17
+ {
18
+ $filename = "roi_hunter_staging_active";
19
+ $io = new Varien_Io_File();
20
+ $io->open(array("path" => Mage::getBaseDir()));
21
+ if ($io->fileExists($filename)) {
22
+ return true;
23
+ }
24
+ else {
25
+ return false;
26
+ }
27
+ }
28
+
29
+ public function getIframeBaseUrl()
30
+ {
31
+ if ($this->isStagingActive()) {
32
+ return "//goostav-fe-staging.roihunter.com/";
33
+ }
34
+ else {
35
+ return "//magento.roihunter.com/";
36
+ }
37
+ }
38
+
39
  public function getDefaultStoreId()
40
  {
41
  return Mage::app()
app/code/community/Businessfactory/Roihuntereasy/Block/CheckoutAnalytics.php CHANGED
@@ -4,40 +4,43 @@ class Businessfactory_Roihuntereasy_Block_CheckoutAnalytics extends Businessfact
4
 
5
  protected $prodId;
6
  protected $prodPrice;
 
7
 
8
  public function _toHtml() {
9
  try {
10
  // find out if session was set
11
- $product_remarketing_base64 = Mage::getSingleton("customer/session")->getMyValue();
12
- $product_remarketing_json = base64_decode($product_remarketing_base64);
13
- $product_remarketing = json_decode($product_remarketing_json, true);
14
 
15
- if ($product_remarketing && array_key_exists('pagetype', $product_remarketing)) {
16
- $pagetype = $product_remarketing['pagetype'];
17
 
18
  // render template with remarketing tag
19
- if ($pagetype === "checkout" && $product_remarketing) {
20
- $this->prodId = $product_remarketing['id'];
21
- $this->prodPrice = $product_remarketing['price'];
 
22
 
23
  // unset session value
24
- Mage::getSingleton('customer/session')->unsMyValue();
25
 
26
  return parent::_toHtml();
27
  }
28
  }
29
  } catch (Exception $exception) {
30
- Mage::log(__METHOD__ . " exception.", null, 'errors.log');
31
- Mage::log($exception, null, 'errors.log');
32
  }
33
 
34
- return '';
35
  }
36
 
37
  public function getProdId()
38
  {
39
  if (!$this->prodId) {
40
- Mage::log("Product ID not found during " . __METHOD__, null, 'errors.log');
 
41
  }
42
  return json_encode($this->prodId);
43
  }
@@ -45,8 +48,40 @@ class Businessfactory_Roihuntereasy_Block_CheckoutAnalytics extends Businessfact
45
  public function getProdPrice()
46
  {
47
  if (!$this->prodPrice) {
48
- Mage::log("Product price not found during " . __METHOD__, null, 'errors.log');
 
49
  }
50
  return $this->prodPrice;
51
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
  }
4
 
5
  protected $prodId;
6
  protected $prodPrice;
7
+ protected $conversionCurrency;
8
 
9
  public function _toHtml() {
10
  try {
11
  // find out if session was set
12
+ $productRemarketingBase64 = Mage::getSingleton("customer/session")->getMyValue();
13
+ $productRemarketingJson = base64_decode($productRemarketingBase64);
14
+ $productRemarketing = json_decode($productRemarketingJson, true);
15
 
16
+ if ($productRemarketing && array_key_exists("pagetype", $productRemarketing)) {
17
+ $pagetype = $productRemarketing["pagetype"];
18
 
19
  // render template with remarketing tag
20
+ if ($pagetype === "checkout") {
21
+ $this->prodId = $productRemarketing["id"];
22
+ $this->prodPrice = $productRemarketing["price"];
23
+ $this->conversionCurrency = $productRemarketing["currency"];
24
 
25
  // unset session value
26
+ Mage::getSingleton("customer/session")->unsMyValue();
27
 
28
  return parent::_toHtml();
29
  }
30
  }
31
  } catch (Exception $exception) {
32
+ Mage::log(__METHOD__ . " exception.", null, "errors.log");
33
+ Mage::log($exception->getMessage(), null, "errors.log");
34
  }
35
 
36
+ return "";
37
  }
38
 
39
  public function getProdId()
40
  {
41
  if (!$this->prodId) {
42
+ Mage::log("Product ID not found during " . __METHOD__, null, "errors.log");
43
+ return null;
44
  }
45
  return json_encode($this->prodId);
46
  }
48
  public function getProdPrice()
49
  {
50
  if (!$this->prodPrice) {
51
+ Mage::log("Product price not found during " . __METHOD__, null, "errors.log");
52
+ return null;
53
  }
54
  return $this->prodPrice;
55
  }
56
+
57
+ public function getConversionLabel()
58
+ {
59
+ try {
60
+ $collection=$this->getCollection();
61
+
62
+ if (($mainItem = ($collection->getLastItem())) == NULL) {
63
+ Mage::log("Table record not found during " . __METHOD__, null, "errors.log");
64
+ return null;
65
+ }
66
+
67
+ if (($conversionLabel = $mainItem->getConversionLabel()) == NULL) {
68
+ Mage::log("Conversion label not found during " . __METHOD__, null, "errors.log");
69
+ return null;
70
+ }
71
+
72
+ return $conversionLabel;
73
+ } catch (Exception $exception) {
74
+ Mage::log(__METHOD__ . " exception.", null, "errors.log");
75
+ Mage::log($exception->getMessage(), null, "errors.log");
76
+ return null;
77
+ }
78
+ }
79
+
80
+ public function getConversionCurrency()
81
+ {
82
+ if (!$this->conversionCurrency) {
83
+ Mage::log("Conversion currency not found during " . __METHOD__, null, "errors.log");
84
+ }
85
+ return $this->conversionCurrency;
86
+ }
87
  }
app/code/community/Businessfactory/Roihuntereasy/Model/CheckoutObserver.php CHANGED
@@ -4,7 +4,7 @@ class Businessfactory_Roihuntereasy_Model_CheckoutObserver extends Mage_Core_Mod
4
  {
5
  public function _construct()
6
  {
7
- $this->_init('roihuntereasy/roihuntereasy');
8
  }
9
 
10
  public function setRemarketingTag(Varien_Event_Observer $observer)
@@ -17,39 +17,41 @@ class Businessfactory_Roihuntereasy_Model_CheckoutObserver extends Mage_Core_Mod
17
  }
18
 
19
  $conversionValue = 0;
 
20
  $productIds = array();
21
  $configurableParentItems = array();
22
  $configurableChildItems = array();
23
 
24
- $collection = Mage::getResourceModel('sales/order_collection')
25
- ->addFieldToFilter('entity_id', array('in' => $orderIds));
26
 
27
  foreach ($collection as $order) {
28
  $conversionValue += $order->getBaseGrandTotal();
 
29
 
30
  // returns all order items
31
- // configurable items are separated to two items - one simple with parent_item_id and one configurable with item_id
32
  $items = $order->getAllItems();
33
  foreach ($items as $item) {
34
- $parent_item_id = $item->getParentItemId();
35
- $product_type = $item->getProductType();
36
 
37
- if ($parent_item_id == null) {
38
  // simple product - write directly to the result IDs array
39
- if ($product_type == "simple") {
40
  array_push($productIds, "mag_".$item->getProductId());
41
- Mage::log("Writing simple product", null, 'debug.log');
42
  }
43
  // configurable parent product
44
- else if ($product_type == "configurable") {
45
  array_push($configurableParentItems, $item);
46
- Mage::log("Storing configurable parent product", null, 'debug.log');
47
  }
48
  }
49
  // configurable child product
50
  else {
51
  array_push($configurableChildItems, $item);
52
- Mage::log("Storing configurable child product", null, 'debug.log');
53
  }
54
  }
55
  }
@@ -57,11 +59,9 @@ class Businessfactory_Roihuntereasy_Model_CheckoutObserver extends Mage_Core_Mod
57
  // create map of parent IDS : parent objects
58
  $parentItemIdToProductIdMap = array();
59
  foreach ($configurableParentItems as $item) {
60
- $parentItemIdToProductIdMap[$item['item_id']] = $item['product_id'];
61
  }
62
 
63
- Mage::log("Configurable parent products map: %s" % ($parentItemIdToProductIdMap), null, 'debug.log');
64
-
65
  // iterate over children items a find parent item in the map
66
  foreach ($configurableChildItems as $item) {
67
  $id = "mag_".$parentItemIdToProductIdMap[$item["parent_item_id"]]."_".$item["product_id"];
@@ -69,21 +69,25 @@ class Businessfactory_Roihuntereasy_Model_CheckoutObserver extends Mage_Core_Mod
69
  }
70
 
71
  // create Google Adwords data
72
- $checkout_remarketing_data = array(
73
- 'pagetype' => 'checkout',
74
- 'id' => $productIds,
75
- 'price' => $conversionValue
 
76
  );
77
- $checkout_remarketing_json = json_encode($checkout_remarketing_data);
78
- $checkout_remarketing_base64 = base64_encode($checkout_remarketing_json);
 
 
 
79
 
80
  // set session
81
- Mage::getSingleton('customer/session')->setMyValue($checkout_remarketing_base64);
82
 
83
  return $this;
84
  } catch (Exception $exception) {
85
- Mage::log(__METHOD__ . " exception.", null, 'errors.log');
86
- Mage::log($exception, null, 'errors.log');
87
  }
88
  }
89
  }
4
  {
5
  public function _construct()
6
  {
7
+ $this->_init("roihuntereasy/roihuntereasy");
8
  }
9
 
10
  public function setRemarketingTag(Varien_Event_Observer $observer)
17
  }
18
 
19
  $conversionValue = 0;
20
+ $currency = null;
21
  $productIds = array();
22
  $configurableParentItems = array();
23
  $configurableChildItems = array();
24
 
25
+ $collection = Mage::getResourceModel("sales/order_collection")
26
+ ->addFieldToFilter("entity_id", array("in" => $orderIds));
27
 
28
  foreach ($collection as $order) {
29
  $conversionValue += $order->getBaseGrandTotal();
30
+ $currency = $order->getStoreCurrencyCode();
31
 
32
  // returns all order items
33
+ // configurable items are divided into two items - one simple with parent_item_id and one configurable with item_id
34
  $items = $order->getAllItems();
35
  foreach ($items as $item) {
36
+ $parentItemId = $item->getParentItemId();
37
+ $productType = $item->getProductType();
38
 
39
+ if ($parentItemId == null) {
40
  // simple product - write directly to the result IDs array
41
+ if ($productType == "simple") {
42
  array_push($productIds, "mag_".$item->getProductId());
43
+ Mage::log("Writing simple product", null, "debug.log");
44
  }
45
  // configurable parent product
46
+ else if ($productType == "configurable") {
47
  array_push($configurableParentItems, $item);
48
+ Mage::log("Storing configurable parent product", null, "debug.log");
49
  }
50
  }
51
  // configurable child product
52
  else {
53
  array_push($configurableChildItems, $item);
54
+ Mage::log("Storing configurable child product", null, "debug.log");
55
  }
56
  }
57
  }
59
  // create map of parent IDS : parent objects
60
  $parentItemIdToProductIdMap = array();
61
  foreach ($configurableParentItems as $item) {
62
+ $parentItemIdToProductIdMap[$item["item_id"]] = $item["product_id"];
63
  }
64
 
 
 
65
  // iterate over children items a find parent item in the map
66
  foreach ($configurableChildItems as $item) {
67
  $id = "mag_".$parentItemIdToProductIdMap[$item["parent_item_id"]]."_".$item["product_id"];
69
  }
70
 
71
  // create Google Adwords data
72
+ $checkoutRemarketingData = array(
73
+ "pagetype" => "checkout",
74
+ "id" => $productIds,
75
+ "price" => $conversionValue,
76
+ "currency" => $currency
77
  );
78
+
79
+ Mage::log("Setting temporary customer session value: ".json_encode($checkoutRemarketingData), null, "debug.log");
80
+
81
+ $checkoutRemarketingJson = json_encode($checkoutRemarketingData);
82
+ $checkout_RemarketingBase64 = base64_encode($checkoutRemarketingJson);
83
 
84
  // set session
85
+ Mage::getSingleton("customer/session")->setMyValue($checkout_RemarketingBase64);
86
 
87
  return $this;
88
  } catch (Exception $exception) {
89
+ Mage::log(__METHOD__ . " exception.", null, "errors.log");
90
+ Mage::log($exception, null, "errors.log");
91
  }
92
  }
93
  }
app/code/community/Businessfactory/Roihuntereasy/Model/Cron.php CHANGED
@@ -7,25 +7,33 @@ class Businessfactory_Roihuntereasy_Model_Cron extends Mage_Core_Model_Abstract
7
  parent::_construct();
8
  }
9
 
10
- public function test() {
11
- Mage::log("Cron schedule running.", null, "cron.log");
 
 
 
 
 
 
 
 
12
  }
13
 
14
  /**
15
  * Method start new feed creation process, if not another feed creation process running.
16
  */
17
- public function createFeed()
18
  {
19
- Mage::log(__METHOD__ . " cron", null, 'cron.log');
20
- $filename = "businessFactoryRoiHunterEasyFeedSign";
21
  $io = new Varien_Io_File();
22
 
23
  try {
24
  $io->setAllowCreateFolders(true);
25
- $io->open(array('path' => Mage::getBaseDir()));
26
 
27
  if ($io->fileExists($filename)) {
28
- Mage::log("Feed generation already running.", null, 'cron.log');
29
  return false;
30
  }
31
 
@@ -34,7 +42,7 @@ class Businessfactory_Roihuntereasy_Model_Cron extends Mage_Core_Model_Abstract
34
  $io->streamClose();
35
 
36
  // Generate feed
37
- $this->generateAndSaveFeed();
38
 
39
  // Delete file
40
  $io->rm($filename);
@@ -43,8 +51,8 @@ class Businessfactory_Roihuntereasy_Model_Cron extends Mage_Core_Model_Abstract
43
 
44
  return true;
45
  } catch (Exception $exception) {
46
- Mage::log(__METHOD__ . " exception.", null, 'errors.log');
47
- Mage::log($exception, null, 'errors.log');
48
 
49
  // Try delete file also when exception occurred.
50
  try {
@@ -52,8 +60,8 @@ class Businessfactory_Roihuntereasy_Model_Cron extends Mage_Core_Model_Abstract
52
 
53
  $io->close();
54
  } catch (Exception $exception) {
55
- Mage::log(__METHOD__ . " exception.", null, 'errors.log');
56
- Mage::log($exception, null, 'errors.log');
57
  }
58
  return false;
59
  }
@@ -62,102 +70,53 @@ class Businessfactory_Roihuntereasy_Model_Cron extends Mage_Core_Model_Abstract
62
  /**
63
  * Feed generation function
64
  */
65
- private function generateAndSaveFeed()
66
  {
67
- $pathTemp = "roi_hunter_easy_feed_temp.xml";
68
- $pathFinal = "roi_hunter_easy_feed_final.xml";
 
 
69
 
 
70
  $io = new Varien_Io_File();
71
  $io->setAllowCreateFolders(true);
72
- $io->open(array('path' => Mage::getBaseDir() . "/feeds"));
73
 
74
- // Clear file
75
  if ($io->fileExists($pathTemp)) {
76
  $io->rm($pathTemp);
77
  }
78
  $io->streamOpen($pathTemp);
79
 
 
 
 
 
 
 
 
 
 
 
80
  try {
81
- $xmlWriter = new XMLWriter();
82
- $xmlWriter->openMemory();
83
- $xmlWriter->startDocument('1.0', 'UTF-8');
84
- $xmlWriter->setIndent(true);
85
-
86
- $xmlWriter->startElement('rss');
87
- $xmlWriter->writeAttribute('version', '2.0');
88
- $xmlWriter->writeAttributeNs('xmlns', 'g', null, 'http://base.google.com/ns/1.0');
89
- $xmlWriter->startElement('channel');
90
- $xmlWriter->writeElement('title', 'ROI Hunter Easy - Magento data feed');
91
- $xmlWriter->writeElement('description', 'Magento data feed used in Google Merchants');
92
- $xmlWriter->writeElement('link', Mage::app()->getStore()->getBaseUrl());
93
-
94
- $total_time_start = microtime(true);
95
- $time_start = microtime(true);
96
- $products = $this->getProductCollection();
97
- $time_end = microtime(true);
98
- $execution_time = ($time_end - $time_start);
99
- Mage::log('getProductCollection count: ' . count($products) . '. Execution time: ' . $execution_time, null, 'cron.log');
100
-
101
- $this->count = 0;
102
-
103
- // debug variables
104
- $limit_enabled = false;
105
- $simple_products_count = 0;
106
- $configurable_products_count = 0;
107
- $simple_products_limit = 2;
108
- $configurable_products_limit = 1;
109
-
110
- foreach ($products as $_product) {
111
-
112
- switch ($_product->getTypeId()) {
113
- case 'downloadable':
114
- if ($_product->getPrice() <= 0) {
115
- // $this->_logger->info("Skip this");
116
- break;
117
- }
118
- // Else same processing as simple product
119
- case 'simple':
120
- if (!$limit_enabled || $simple_products_count < $simple_products_limit) {
121
- $this->write_simple_product($_product, $xmlWriter);
122
- $simple_products_count++;
123
- }
124
- break;
125
- case 'configurable':
126
- if (!$limit_enabled || $configurable_products_count < $configurable_products_limit) {
127
- $this->write_configurable_product($_product, $xmlWriter);
128
- $configurable_products_count++;
129
- }
130
- break;
131
- }
132
- if ($limit_enabled && $simple_products_count >= $simple_products_limit && $configurable_products_count >= $configurable_products_limit) {
133
- break;
134
- }
135
-
136
- $this->count++;
137
- if ($this->count >= 512) {
138
- $this->count = 0;
139
- // After each 512 products flush memory to file.
140
- $io->streamWrite($xmlWriter->flush());
141
- }
142
  }
143
 
144
- $xmlWriter->endElement();
145
- $xmlWriter->endElement();
146
- $xmlWriter->endDocument();
147
-
148
- // Final memory flush, rename temporary file and feed is done.
149
- $io->streamWrite($xmlWriter->flush());
150
  $io->streamClose();
151
 
152
  if ($io->mv($pathTemp, $pathFinal)) {
153
- Mage::log("Created feed renamed successful", null, 'cron.log');
154
  } else {
155
- Mage::log("ERROR: Created feed renamed unsuccessful", null, 'cron.log');
156
  }
157
 
158
- $total_time_end = microtime(true);
159
- $total_execution_time = ($total_time_end - $total_time_start);
160
- Mage::log('total execution time: ' . $total_execution_time, null, 'cron.log');
161
  } catch (Exception $e) {
162
  Mage::throwException($e);
163
  }
@@ -167,28 +126,179 @@ class Businessfactory_Roihuntereasy_Model_Cron extends Mage_Core_Model_Abstract
167
  return true;
168
  }
169
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
170
  public function getProductCollection()
171
  {
172
- $collection = Mage::getModel('catalog/product')->getCollection();
173
 
174
  // select necessary attributes
175
- $collection->addAttributeToSelect('name');
176
- $collection->addAttributeToSelect('short_description');
177
- $collection->addAttributeToSelect('description');
178
- $collection->addAttributeToSelect('price');
179
- $collection->addAttributeToSelect('special_price');
180
- $collection->addAttributeToSelect('size');
181
- $collection->addAttributeToSelect('color');
182
- $collection->addAttributeToSelect('pattern');
183
- $collection->addAttributeToSelect('image');
184
 
185
  // Allow only visible products
186
  $visibility = array(
187
  Mage_Catalog_Model_Product_Visibility::VISIBILITY_BOTH,
188
  Mage_Catalog_Model_Product_Visibility::VISIBILITY_IN_CATALOG
189
  );
190
- $collection->addAttributeToFilter('visibility', $visibility);
191
- $collection->addAttributeToFilter('status', Mage_Catalog_Model_Product_Status::STATUS_ENABLED);
192
 
193
  // setting correct Product URL
194
  $collection->addUrlRewrite();
@@ -196,34 +306,66 @@ class Businessfactory_Roihuntereasy_Model_Cron extends Mage_Core_Model_Abstract
196
  ->getDefaultStoreView()
197
  ->getStoreId();
198
  $collection->setStoreId($storeId);
 
 
199
  Mage::app()->setCurrentStore($storeId);
200
 
201
  $collection->load();
202
 
203
- Mage::log("Default store ID: " . $storeId, null, 'cron.log');
204
 
205
  return $collection;
206
  }
207
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
208
  /**
209
  * @param $_product
210
  * @param XMLWriter $xmlWriter
211
  */
212
- private function write_simple_product($_product, $xmlWriter)
213
  {
214
- $xmlWriter->startElement('item');
215
 
216
- // ID belongs to the simple product's SKU
217
- $xmlWriter->writeElement('g:id', "mag_".$_product->getId());
218
- $xmlWriter->writeElement('g:display_ads_id', "mag_".$_product->getId());
219
 
220
  // process common attributes
221
- $this->write_parent_product_attributes($_product, $xmlWriter);
222
  // process advanced attributes
223
- $this->write_child_product_attributes($_product, $xmlWriter);
224
  // categories
225
- $catCollection = $this->get_product_types($_product);
226
- $this->write_product_types($catCollection, $xmlWriter);
227
 
228
  $xmlWriter->endElement();
229
  }
@@ -232,171 +374,221 @@ class Businessfactory_Roihuntereasy_Model_Cron extends Mage_Core_Model_Abstract
232
  * @param Mixed $_product
233
  * @param XMLWriter $xmlWriter
234
  */
235
- function write_parent_product_attributes($_product, $xmlWriter)
236
  {
237
- $xmlWriter->writeElement('g:title', $_product->getName());
238
- $xmlWriter->writeElement('g:description', $this->get_description($_product));
239
  // Product URL
240
- // $_product->getData('request_path') can return product handle like - aviator-sunglasses.html
241
- $xmlWriter->writeElement('g:link', $_product->getUrlInStore());
242
 
243
  // replaced getAttributeText with safer option
244
- $attributeCode = 'manufacturer';
245
  if ($_product->getData($attributeCode) !== null){
246
- $xmlWriter->writeElement('g:brand', $_product->getAttributeText($attributeCode));
247
- }
248
-
249
- $xmlWriter->writeElement('g:condition', 'new');
250
- // TODO add more attributes if needed.
251
- // $xmlWriter->writeElement('g:size_system', 'uk');
252
- // $xmlWriter->writeElement('g:age_group', 'adult');
253
-
254
- // $xmlWriter->writeElement('g:identifier_exists', 'TRUE');
255
- // $xmlWriter->writeElement('g:adult', $this->do_is_adult($_product));
256
- }
257
-
258
- // /**
259
- // * @param Mixed $_product
260
- // * @return string
261
- // */
262
- // function do_is_adult($_product)
263
- // {
264
- // // TODO add decision if needed.
265
- //// switch ($_product->getAttributeText('familysafe')) {
266
- //// case 'No':
267
- //// $isadult = "FALSE";
268
- //// default:
269
- //// $isadult = "TRUE";
270
- //// }
271
- // return ("FALSE");
272
- // }
273
-
274
- /**
275
- * @param Mixed $product
276
- * @return mixed
277
- */
278
- function get_description($product)
279
- {
280
- $description = $product->getShortDescription();
281
- if (!$description) {
282
- $description = $product->getDescription();
283
  }
284
- return ($description);
285
- }
286
-
287
- /**
288
- * @param Mixed $product
289
- * @return string
290
- */
291
- function get_image_url($product)
292
- {
293
- $productMediaConfig = Mage::getModel('catalog/product_media_config');
294
- $baseImageUrl = $productMediaConfig->getMediaUrl($product->getImage());
295
 
296
- return $baseImageUrl;
297
  }
298
 
299
  /**
300
  * @param Mixed $_product
301
  * @param XMLWriter $xmlWriter
302
  */
303
- function write_child_product_attributes($_product, $xmlWriter)
304
  {
305
- $xmlWriter->writeElement('g:image_link', $this->get_image_url($_product));
306
 
307
- // $this->_logger->debug('gtin: ' . $_product->getEan());
308
- $xmlWriter->writeElement('g:mpn', $_product->getSku());
309
  if (strlen($_product->getEan()) > 7) {
310
- $xmlWriter->writeElement('g:gtin', $_product->getEan());
311
  }
312
 
313
- $xmlWriter->writeElement('g:price', $_product->getPrice());
314
- $xmlWriter->writeElement('g:sale_price', $_product->getSpecialPrice());
315
  // replaced getAttributeText with safer option
316
- $attributeCode = 'color';
317
  if ($_product->getData($attributeCode) !== null){
318
- $xmlWriter->writeElement('g:color', $_product->getAttributeText($attributeCode));
319
  }
320
  // replaced getAttributeText with safer option
321
- $attributeCode = 'size';
322
  if ($_product->getData($attributeCode) !== null){
323
- $xmlWriter->writeElement('g:size', $_product->getAttributeText($attributeCode));
324
  }
325
 
326
- $xmlWriter->writeElement('g:availability', $this->do_isinstock($_product));
 
 
 
 
 
 
 
 
 
 
 
 
327
  }
328
 
329
  /**
330
  * @param Mixed $_product
331
  * @return string
332
  */
333
- function do_isinstock($_product)
334
  {
335
  $stockItem = $_product->getStockItem();
336
  if($stockItem->getIsInStock())
337
  {
338
- $stockval = 'in stock';
339
  }
340
  else
341
  {
342
- $stockval = 'out of stock';
343
  }
344
 
345
  return $stockval;
346
  }
347
 
348
  /**
349
- * @param Mixed $catCollection
350
- * @param XMLWriter $xmlWriter
351
  */
352
- function write_product_types($catCollection, $xmlWriter)
353
  {
354
- /** @var Mixed $category */
355
- foreach ($catCollection as $category) {
356
- $xmlWriter->writeElement('g:product_type', $category->getName());
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
357
  }
 
 
358
  }
359
 
360
  /**
361
- * @param Mixed $_product
362
- * @return mixed
363
  */
364
- function get_product_types($_product)
365
  {
366
- // SELECT name FROM category
367
- // if I want to load more attributes, I need to select them first
368
- // loading and selecting is processor intensive! Selecting more attributes will result in longer delay!
369
- return $_product->getCategoryCollection()->addAttributeToSelect('name')->load();
 
 
 
370
  }
371
 
372
  /**
373
- * @param Mixed $_product
374
- * @param XMLWriter $xmlWriter
 
 
 
 
 
 
 
 
 
375
  */
376
- private function write_configurable_product($_product, $xmlWriter)
377
  {
378
- $catCollection = $this->get_product_types($_product);
 
 
 
 
 
 
379
 
380
- $conf = Mage::getModel('catalog/product_type_configurable')->setProduct($_product);
381
- $simple_collection = $conf->getUsedProductCollection()->addAttributeToSelect('*')->addFilterByRequiredOptions();
 
 
 
 
 
 
 
 
 
 
 
382
 
383
- foreach ($simple_collection as $_childproduct) {
384
- $xmlWriter->startElement('item');
 
 
 
 
 
 
385
 
386
- // ID belongs to the child product's ID to make this product unique
387
- $xmlWriter->writeElement('g:id', "mag_".$_product->getId()."_".$_childproduct->getId());
388
- $xmlWriter->writeElement('g:item_group_id', "mag_".$_product->getId());
389
- $xmlWriter->writeElement('g:display_ads_id', "mag_".$_product->getId()."_".$_childproduct->getId());
 
 
 
 
 
 
 
 
390
 
391
- // process common attributes
392
- $this->write_parent_product_attributes($_product, $xmlWriter);
393
- // process advanced attributes
394
- $this->write_child_product_attributes($_childproduct, $xmlWriter);
395
- // categories
396
- $this->write_product_types($catCollection, $xmlWriter);
 
397
 
398
- $xmlWriter->endElement();
399
- $this->count++;
 
 
 
 
 
 
400
  }
 
 
401
  }
402
  }
7
  parent::_construct();
8
  }
9
 
10
+ /**
11
+ * Method start new feed creation process from cron schedule.
12
+ */
13
+ public function scheduleFeed($schedule) {
14
+ Mage::log(__METHOD__ . ": scheduled feed generation. ", null, "cron.log");
15
+
16
+ $jobsRoot = Mage::getConfig()->getNode("crontab/jobs");
17
+ $jobConfig = $jobsRoot->{$schedule->getJobCode()};
18
+ $fileFormat = (string) $jobConfig->format;
19
+ $this->createFeed($fileFormat);
20
  }
21
 
22
  /**
23
  * Method start new feed creation process, if not another feed creation process running.
24
  */
25
+ public function createFeed($fileFormat="xml")
26
  {
27
+ Mage::log($fileFormat . ": " . __METHOD__ . " cron", null, "cron.log");
28
+ $filename = "businessFactoryRoiHunterEasyFeedSign" . $fileFormat;
29
  $io = new Varien_Io_File();
30
 
31
  try {
32
  $io->setAllowCreateFolders(true);
33
+ $io->open(array("path" => Mage::getBaseDir()));
34
 
35
  if ($io->fileExists($filename)) {
36
+ Mage::log($fileFormat. ": Feed generation already running.", null, "cron.log");
37
  return false;
38
  }
39
 
42
  $io->streamClose();
43
 
44
  // Generate feed
45
+ $this->generateAndSaveFeed($fileFormat);
46
 
47
  // Delete file
48
  $io->rm($filename);
51
 
52
  return true;
53
  } catch (Exception $exception) {
54
+ Mage::log($fileFormat . ": " . __METHOD__ . " exception.", null, "errors.log");
55
+ Mage::log($exception->getMessage(), null, "errors.log");
56
 
57
  // Try delete file also when exception occurred.
58
  try {
60
 
61
  $io->close();
62
  } catch (Exception $exception) {
63
+ Mage::log($fileFormat . ": " . __METHOD__ . " exception.", null, "errors.log");
64
+ Mage::log($exception->getMessage(), null, "errors.log");
65
  }
66
  return false;
67
  }
70
  /**
71
  * Feed generation function
72
  */
73
+ private function generateAndSaveFeed($fileFormat)
74
  {
75
+ // create tmp file for writing blocks of the products
76
+ $pathTemp = "roi_hunter_easy_feed_temp." . $fileFormat;
77
+ // set the name of the final file (tmp is renamed to this named after the operation is completed)
78
+ $pathFinal = "roi_hunter_easy_feed_final." . $fileFormat;
79
 
80
+ // create IO Stream for writing
81
  $io = new Varien_Io_File();
82
  $io->setAllowCreateFolders(true);
83
+ $io->open(array("path" => Mage::getBaseDir() . "/feeds"));
84
 
85
+ // remove the temporary file if exists
86
  if ($io->fileExists($pathTemp)) {
87
  $io->rm($pathTemp);
88
  }
89
  $io->streamOpen($pathTemp);
90
 
91
+ // get collection of all products
92
+ $products = $this->getProductCollection();
93
+
94
+ // measurement variables
95
+ $totalTimeStart = microtime(true);
96
+ $timeStart = microtime(true);
97
+ $timeEnd = microtime(true);
98
+ $executionTime = ($timeEnd - $timeStart);
99
+ Mage::log("getProductCollection count: " . count($products) . ". Execution time: " . $executionTime, null, "cron.log");
100
+
101
  try {
102
+ if ($fileFormat === "xml") {
103
+ $this->generateAndSaveFeedXML($products, $io);
104
+ }
105
+ else if ($fileFormat === "csv") {
106
+ $this->generateAndSaveFeedCSV($products, $io);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
107
  }
108
 
 
 
 
 
 
 
109
  $io->streamClose();
110
 
111
  if ($io->mv($pathTemp, $pathFinal)) {
112
+ Mage::log("Created feed renamed successful", null, "cron.log");
113
  } else {
114
+ Mage::log("ERROR: Created feed renamed unsuccessful", null, "cron.log");
115
  }
116
 
117
+ $totalTimeEnd = microtime(true);
118
+ $totalExecutionTime = ($totalTimeEnd - $totalTimeStart);
119
+ Mage::log("total execution time: " . $totalExecutionTime, null, "cron.log");
120
  } catch (Exception $e) {
121
  Mage::throwException($e);
122
  }
126
  return true;
127
  }
128
 
129
+ /**
130
+ * Feed generation function
131
+ */
132
+ private function generateAndSaveFeedCSV($products, $io) {
133
+ // CSV headers
134
+ $csvHeader = array(
135
+ "ID",
136
+ "Item title",
137
+ "Final URL",
138
+ "Image URL",
139
+ "Item description",
140
+ "Price",
141
+ "Sale price"
142
+ );
143
+
144
+ // write headers to CSV file
145
+ $io->streamWriteCsv($csvHeader);
146
+
147
+ $this->count = 0;
148
+ foreach ($products as $_product) {
149
+ switch ($_product->getTypeId()) {
150
+ case "downloadable":
151
+ if ($_product->getPrice() <= 0) {
152
+ break;
153
+ }
154
+ // Else same processing as simple product
155
+ case "simple":
156
+ $productDict = $this->getSimpleProductDict($_product);
157
+ $io->streamWriteCsv($productDict);
158
+ break;
159
+ case "configurable":
160
+ $productDictArray = $this->getConfigurableProductDict($_product);
161
+ foreach ($productDictArray as $productDict){
162
+ $io->streamWriteCsv($productDict);
163
+ }
164
+ break;
165
+ }
166
+ }
167
+
168
+ }
169
+
170
+ /**
171
+ * @param Mixed $_product
172
+ * @param XMLWriter $xmlWriter
173
+ */
174
+ private function getConfigurableProductDict($_product)
175
+ {
176
+ $conf = Mage::getModel("catalog/product_type_configurable")->setProduct($_product);
177
+ $simpleCollection = $conf->getUsedProductCollection()->addAttributeToSelect("*")->addFilterByRequiredOptions();
178
+
179
+ $productArray = array();
180
+
181
+ foreach ($simpleCollection as $_childproduct) {
182
+ $productDict = array(
183
+ "ID" => $this->getId($_product, $_childproduct),
184
+ "Item title" => $this->getTitle($_product),
185
+ "Final URL" => $this->getProductUrl($_product),
186
+ "Image URL" => $this->getImageUrl($_childproduct),
187
+ "Item description" => $this->getDescription($_product),
188
+ "Price" => $this->getPrice($_childproduct, true),
189
+ "Sale price" => $this->getSalePrice($_childproduct, true),
190
+ );
191
+ array_push($productArray, $productDict);
192
+ }
193
+ return $productArray;
194
+ }
195
+
196
+ /**
197
+ * @param $_product
198
+ * @param XMLWriter $xmlWriter
199
+ */
200
+ private function getSimpleProductDict($_product)
201
+ {
202
+ $productDict = array(
203
+ "ID" => $this->getId($_product, null),
204
+ "Item title" => $this->getTitle($_product),
205
+ "Final URL" => $this->getProductUrl($_product),
206
+ "Image URL" => $this->getImageUrl($_product),
207
+ "Item description" => $this->getDescription($_product),
208
+ "Price" => $this->getPrice($_product, true),
209
+ "Sale price" => $this->getSalePrice($_product, true),
210
+ );
211
+ return $productDict;
212
+ }
213
+
214
+ /**
215
+ * Feed generation function
216
+ */
217
+ private function generateAndSaveFeedXML($products, $io) {
218
+ // debug variables
219
+ $limitEnabled = false;
220
+ $simpleProductsCount = 0;
221
+ $configurableProductsCount = 0;
222
+ $simpleProductsLimit = 1;
223
+ $configurableProductsLimit = 0;
224
+
225
+ $xmlWriter = new XMLWriter();
226
+ $xmlWriter->openMemory();
227
+ $xmlWriter->startDocument("1.0", "UTF-8");
228
+ $xmlWriter->setIndent(true);
229
+
230
+ $xmlWriter->startElement("rss");
231
+ $xmlWriter->writeAttribute("version", "2.0");
232
+ $xmlWriter->writeAttributeNs("xmlns", "g", null, "http://base.google.com/ns/1.0");
233
+ $xmlWriter->startElement("channel");
234
+ $xmlWriter->writeElement("title", "ROI Hunter Easy - Magento data feed");
235
+ $xmlWriter->writeElement("description", "Magento data feed used in Google Merchants");
236
+ $xmlWriter->writeElement("link", Mage::app()->getStore()->getBaseUrl());
237
+
238
+ $this->count = 0;
239
+ foreach ($products as $_product) {
240
+
241
+ switch ($_product->getTypeId()) {
242
+ case "downloadable":
243
+ if ($_product->getPrice() <= 0) {
244
+ break;
245
+ }
246
+ // Else same processing as simple product
247
+ case "simple":
248
+ if (!$limitEnabled || $simpleProductsCount < $simpleProductsLimit) {
249
+ $this->writeSimpleProductXML($_product, $xmlWriter);
250
+ $simpleProductsCount++;
251
+ }
252
+ break;
253
+ case "configurable":
254
+ if (!$limitEnabled || $configurableProductsCount < $configurableProductsLimit) {
255
+ $this->writeConfigurableProductXML($_product, $xmlWriter);
256
+ $configurableProductsCount++;
257
+ }
258
+ break;
259
+ }
260
+ if ($limitEnabled && $simpleProductsCount >= $simpleProductsLimit && $configurableProductsCount >= $configurableProductsLimit) {
261
+ break;
262
+ }
263
+
264
+ $this->count++;
265
+ if ($this->count >= 512) {
266
+ $this->count = 0;
267
+ // After each 512 products flush memory to file.
268
+ $io->streamWrite($xmlWriter->flush());
269
+ }
270
+ }
271
+
272
+ $xmlWriter->endElement();
273
+ $xmlWriter->endElement();
274
+ $xmlWriter->endDocument();
275
+
276
+ // Final memory flush, rename temporary file and feed is done.
277
+ $io->streamWrite($xmlWriter->flush());
278
+ }
279
+
280
  public function getProductCollection()
281
  {
282
+ $collection = Mage::getModel("catalog/product")->getCollection();
283
 
284
  // select necessary attributes
285
+ $collection->addAttributeToSelect("name");
286
+ $collection->addAttributeToSelect("short_description");
287
+ $collection->addAttributeToSelect("description");
288
+ $collection->addAttributeToSelect("price");
289
+ $collection->addAttributeToSelect("special_price");
290
+ $collection->addAttributeToSelect("size");
291
+ $collection->addAttributeToSelect("color");
292
+ $collection->addAttributeToSelect("pattern");
293
+ $collection->addAttributeToSelect("image");
294
 
295
  // Allow only visible products
296
  $visibility = array(
297
  Mage_Catalog_Model_Product_Visibility::VISIBILITY_BOTH,
298
  Mage_Catalog_Model_Product_Visibility::VISIBILITY_IN_CATALOG
299
  );
300
+ $collection->addAttributeToFilter("visibility", $visibility);
301
+ $collection->addAttributeToFilter("status", Mage_Catalog_Model_Product_Status::STATUS_ENABLED);
302
 
303
  // setting correct Product URL
304
  $collection->addUrlRewrite();
306
  ->getDefaultStoreView()
307
  ->getStoreId();
308
  $collection->setStoreId($storeId);
309
+ // adding website filter removes products unavailable in the store on the frontend
310
+ $collection->addStoreFilter($storeId);
311
  Mage::app()->setCurrentStore($storeId);
312
 
313
  $collection->load();
314
 
315
+ Mage::log("Default store ID: " . $storeId, null, "cron.log");
316
 
317
  return $collection;
318
  }
319
 
320
+ /**
321
+ * @param Mixed $_product
322
+ * @param XMLWriter $xmlWriter
323
+ */
324
+ private function writeConfigurableProductXML($_product, $xmlWriter)
325
+ {
326
+ $catCollection = $this->getProductTypes($_product);
327
+
328
+ $conf = Mage::getModel("catalog/product_type_configurable")->setProduct($_product);
329
+ $simpleCollection = $conf->getUsedProductCollection()->addAttributeToSelect("*")->addFilterByRequiredOptions();
330
+
331
+ foreach ($simpleCollection as $_childproduct) {
332
+ $xmlWriter->startElement("item");
333
+
334
+ // ID belongs to the child product"s ID to make this product unique
335
+ $xmlWriter->writeElement("g:id", $this->getId($_product, $_childproduct));
336
+ $xmlWriter->writeElement("g:item_group_id", $this->getItemGroupId($_product));
337
+ $xmlWriter->writeElement("g:display_ads_id", $this->getDisplayAdsId($_product, $_childproduct));
338
+
339
+ // process common attributes
340
+ $this->writeParentProductAttributesXML($_product, $xmlWriter);
341
+ // process advanced attributes
342
+ $this->writeChildProductAttributesXML($_childproduct, $xmlWriter);
343
+ // categories
344
+ $this->writeProductTypesXml($catCollection, $xmlWriter);
345
+
346
+ $xmlWriter->endElement();
347
+ }
348
+ }
349
+
350
  /**
351
  * @param $_product
352
  * @param XMLWriter $xmlWriter
353
  */
354
+ private function writeSimpleProductXML($_product, $xmlWriter)
355
  {
356
+ $xmlWriter->startElement("item");
357
 
358
+ // ID belongs to the simple product"s SKU
359
+ $xmlWriter->writeElement("g:id", $this->getId($_product, null));
360
+ $xmlWriter->writeElement("g:display_ads_id", $this->getDisplayAdsId($_product, null));
361
 
362
  // process common attributes
363
+ $this->writeParentProductAttributesXML($_product, $xmlWriter);
364
  // process advanced attributes
365
+ $this->writeChildProductAttributesXML($_product, $xmlWriter);
366
  // categories
367
+ $catCollection = $this->getProductTypes($_product);
368
+ $this->writeProductTypesXml($catCollection, $xmlWriter);
369
 
370
  $xmlWriter->endElement();
371
  }
374
  * @param Mixed $_product
375
  * @param XMLWriter $xmlWriter
376
  */
377
+ function writeParentProductAttributesXML($_product, $xmlWriter)
378
  {
379
+ $xmlWriter->writeElement("g:title", $this->getTitle($_product));
380
+ $xmlWriter->writeElement("g:description", $this->getDescription($_product));
381
  // Product URL
382
+ // $_product->getData("request_path") can return product handle like - aviator-sunglasses.html
383
+ $xmlWriter->writeElement("g:link", $this->getProductUrl($_product));
384
 
385
  // replaced getAttributeText with safer option
386
+ $attributeCode = "manufacturer";
387
  if ($_product->getData($attributeCode) !== null){
388
+ $xmlWriter->writeElement("g:brand", $_product->getAttributeText($attributeCode));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
389
  }
 
 
 
 
 
 
 
 
 
 
 
390
 
391
+ $xmlWriter->writeElement("g:condition", "new");
392
  }
393
 
394
  /**
395
  * @param Mixed $_product
396
  * @param XMLWriter $xmlWriter
397
  */
398
+ function writeChildProductAttributesXML($_product, $xmlWriter)
399
  {
400
+ $xmlWriter->writeElement("g:image_link", $this->getImageUrl($_product));
401
 
402
+ // $this->_logger->debug("gtin: " . $_product->getEan());
403
+ $xmlWriter->writeElement("g:mpn", $_product->getSku());
404
  if (strlen($_product->getEan()) > 7) {
405
+ $xmlWriter->writeElement("g:gtin", $_product->getEan());
406
  }
407
 
408
+ $xmlWriter->writeElement("g:price", $this->getPrice($_product));
409
+ $xmlWriter->writeElement("g:sale_price", $this->getSalePrice($_product));
410
  // replaced getAttributeText with safer option
411
+ $attributeCode = "color";
412
  if ($_product->getData($attributeCode) !== null){
413
+ $xmlWriter->writeElement("g:color", $_product->getAttributeText($attributeCode));
414
  }
415
  // replaced getAttributeText with safer option
416
+ $attributeCode = "size";
417
  if ($_product->getData($attributeCode) !== null){
418
+ $xmlWriter->writeElement("g:size", $_product->getAttributeText($attributeCode));
419
  }
420
 
421
+ $xmlWriter->writeElement("g:availability", $this->doIsInStock($_product));
422
+ }
423
+
424
+ /**
425
+ * @param Mixed $catCollection
426
+ * @param XMLWriter $xmlWriter
427
+ */
428
+ function writeProductTypesXML($catCollection, $xmlWriter)
429
+ {
430
+ /** @var Mixed $category */
431
+ foreach ($catCollection as $category) {
432
+ $xmlWriter->writeElement("g:product_type", $category->getName());
433
+ }
434
  }
435
 
436
  /**
437
  * @param Mixed $_product
438
  * @return string
439
  */
440
+ function doIsInStock($_product)
441
  {
442
  $stockItem = $_product->getStockItem();
443
  if($stockItem->getIsInStock())
444
  {
445
+ $stockval = "in stock";
446
  }
447
  else
448
  {
449
+ $stockval = "out of stock";
450
  }
451
 
452
  return $stockval;
453
  }
454
 
455
  /**
456
+ * @param Mixed $_product
457
+ * @return mixed
458
  */
459
+ function getProductTypes($_product)
460
  {
461
+ // SELECT name FROM category
462
+ // if I want to load more attributes, I need to select them first
463
+ // loading and selecting is processor intensive! Selecting more attributes will result in longer delay!
464
+ return $_product->getCategoryCollection()->addAttributeToSelect("name")->load();
465
+ }
466
+
467
+ /**
468
+ * @param Mixed $product
469
+ * @return string price
470
+ */
471
+ function getProductUrl($product)
472
+ {
473
+ return $product->getUrlInStore();
474
+ }
475
+
476
+ /**
477
+ * @param Mixed $product
478
+ * @return string price
479
+ */
480
+ function getCurrency()
481
+ {
482
+ return $currentCurrencyCode = Mage::app()->getStore()->getCurrentCurrencyCode();
483
+ }
484
+
485
+ /**
486
+ * @param Mixed $product
487
+ * @return string price
488
+ */
489
+ function getSalePrice($product, $withCurrency=false)
490
+ {
491
+ $price = $product->getFinalPrice();
492
+
493
+ if ($price && $withCurrency) {
494
+ $price = $price." ".$this->getCurrency();
495
  }
496
+
497
+ return $price;
498
  }
499
 
500
  /**
501
+ * @param Mixed $product
502
+ * @return string price
503
  */
504
+ function getPrice($product, $withCurrency=false)
505
  {
506
+ $price = $product->getPrice();
507
+
508
+ if ($withCurrency) {
509
+ $price = $price." ".$this->getCurrency();
510
+ }
511
+
512
+ return $price;
513
  }
514
 
515
  /**
516
+ * @param Mixed $product
517
+ * @return string item_group_id
518
+ */
519
+ function getItemGroupId($product)
520
+ {
521
+ return "mag_".$product->getId();
522
+ }
523
+
524
+ /**
525
+ * @param Mixed $product
526
+ * @return string display_ads_id
527
  */
528
+ function getDisplayAdsId($product, $childproduct=null)
529
  {
530
+ if ($childproduct) {
531
+ return "mag_".$product->getId()."_".$childproduct->getId();
532
+ }
533
+ else {
534
+ return "mag_".$product->getId();
535
+ }
536
+ }
537
 
538
+ /**
539
+ * @param Mixed $product
540
+ * @return string id
541
+ */
542
+ function getId($product, $childproduct=null)
543
+ {
544
+ if ($childproduct) {
545
+ return "mag_".$product->getId()."_".$childproduct->getId();
546
+ }
547
+ else {
548
+ return "mag_".$product->getId();
549
+ }
550
+ }
551
 
552
+ /**
553
+ * @param Mixed $product
554
+ * @return string title
555
+ */
556
+ function getTitle($product)
557
+ {
558
+ return $product->getName();
559
+ }
560
 
561
+ /**
562
+ * @param Mixed $product
563
+ * @return string description
564
+ */
565
+ function getDescription($product)
566
+ {
567
+ $description = $product->getShortDescription();
568
+ if (!$description) {
569
+ $description = $product->getDescription();
570
+ }
571
+ return $description;
572
+ }
573
 
574
+ /**
575
+ * @param Mixed $product
576
+ * @return string image URL
577
+ */
578
+ function getImageUrl($product)
579
+ {
580
+ $imageUrl = null;
581
 
582
+ // try to retrieve base image URL
583
+ if ($product->getImage() != "no_selection" && $product->getImage()){
584
+ $productMediaConfig = Mage::getModel("catalog/product_media_config");
585
+ $imageUrl = $productMediaConfig->getMediaUrl($product->getImage());
586
+ }
587
+ // retrieve cached image URL
588
+ else {
589
+ $imageUrl = Mage::helper("catalog/image")->init($product, "image");
590
  }
591
+
592
+ return $imageUrl;
593
  }
594
  }
app/code/community/Businessfactory/Roihuntereasy/controllers/CronController.php CHANGED
@@ -4,10 +4,16 @@ class Businessfactory_Roihuntereasy_CronController extends Mage_Core_Controller_
4
  {
5
  protected $cron;
6
 
 
 
7
  public function _construct()
8
  {
9
  parent::_construct();
10
  $this->cron = new Businessfactory_Roihuntereasy_Model_Cron();
 
 
 
 
11
  }
12
 
13
  /**
@@ -39,16 +45,15 @@ class Businessfactory_Roihuntereasy_CronController extends Mage_Core_Controller_
39
  return;
40
  }
41
 
42
- Mage::log("Cron generating started manually.", null, 'cron.log');
43
- $resultCode = $this->cron->createFeed();
44
  if($resultCode == true){
45
- $response->setBody(json_encode('Feed generated.'));
46
  } else {
47
- $response->setBody(json_encode('Feed not generated.'));
48
  }
49
  } catch (Exception $exception) {
50
  Mage::log(__METHOD__ . " exception.", null, 'errors.log');
51
- Mage::log($exception, null, 'errors.log');
52
  Mage::log($request, null, 'errors.log');
53
  $response->setHttpResponseCode(500);
54
  $response->setBody(json_encode('Feed generation failed.'));
@@ -93,27 +98,28 @@ class Businessfactory_Roihuntereasy_CronController extends Mage_Core_Controller_
93
  }
94
  }
95
 
96
- $filename = "businessFactoryRoiHunterEasyFeedSign";
97
- $io = new Varien_Io_File();
98
- $io->open(array('path' => Mage::getBaseDir()));
 
 
99
 
100
- if (!$io->fileExists($filename)) {
101
- $response->setBody(json_encode("Reset already completed."));
102
- }
103
- else {
104
- // try to delete feed generation sign.
105
- $io->rm($filename);
106
- $response->setBody(json_encode("Reset completed."));
 
107
  }
108
 
109
- $io->close();
110
-
111
- Mage::log("Cron generating started manually.", null, 'cron.log');
112
- $resultCode = $this->cron->createFeed();
113
  if($resultCode == true){
114
- $response->setBody(json_encode('Feed generated.'));
115
  } else {
116
- $response->setBody(json_encode('Feed not generated.'));
117
  }
118
  } catch (Exception $exception) {
119
  Mage::log(__METHOD__ . " exception.", null, 'errors.log');
@@ -129,5 +135,14 @@ class Businessfactory_Roihuntereasy_CronController extends Mage_Core_Controller_
129
  }
130
  }
131
 
 
 
 
 
 
 
 
 
 
132
  }
133
 
4
  {
5
  protected $cron;
6
 
7
+ protected $supportedFileFormats;
8
+
9
  public function _construct()
10
  {
11
  parent::_construct();
12
  $this->cron = new Businessfactory_Roihuntereasy_Model_Cron();
13
+ $this->supportedFileFormats = array(
14
+ "xml",
15
+ "csv"
16
+ );
17
  }
18
 
19
  /**
45
  return;
46
  }
47
 
48
+ $resultCode = $this->generateSupportedFeeds();
 
49
  if($resultCode == true){
50
+ $response->setBody(json_encode('Feeds generated.'));
51
  } else {
52
+ $response->setBody(json_encode('One or more feeds not generated. See logs for more info.'));
53
  }
54
  } catch (Exception $exception) {
55
  Mage::log(__METHOD__ . " exception.", null, 'errors.log');
56
+ Mage::log($exception->getMessage(), null, 'errors.log');
57
  Mage::log($request, null, 'errors.log');
58
  $response->setHttpResponseCode(500);
59
  $response->setBody(json_encode('Feed generation failed.'));
98
  }
99
  }
100
 
101
+ // remove file locks
102
+ foreach ($this->supportedFileFormats as $fileFormat) {
103
+ $filename = "businessFactoryRoiHunterEasyFeedSign".$fileFormat;
104
+ $io = new Varien_Io_File();
105
+ $io->open(array('path' => Mage::getBaseDir()));
106
 
107
+ if (!$io->fileExists($filename)) {
108
+ $response->setBody(json_encode("Reset already completed."));
109
+ }
110
+ else {
111
+ // try to delete feed generation sign.
112
+ $io->rm($filename);
113
+ $response->setBody(json_encode("Reset completed."));
114
+ }
115
  }
116
 
117
+ // regenerate feeds
118
+ $resultCode = $this->generateSupportedFeeds();
 
 
119
  if($resultCode == true){
120
+ $response->setBody(json_encode('Feeds generated.'));
121
  } else {
122
+ $response->setBody(json_encode('One or more feeds not generated. See logs for more info.'));
123
  }
124
  } catch (Exception $exception) {
125
  Mage::log(__METHOD__ . " exception.", null, 'errors.log');
135
  }
136
  }
137
 
138
+ protected function generateSupportedFeeds() {
139
+ $resultCode = true;
140
+ foreach ($this->supportedFileFormats as $fileFormat) {
141
+ Mage::log("Cron generating started manually for file format: " . $fileFormat, null, 'cron.log');
142
+ $resultCode = $resultCode && $this->cron->createFeed($fileFormat);
143
+ }
144
+ return $resultCode;
145
+ }
146
+
147
  }
148
 
app/code/community/Businessfactory/Roihuntereasy/controllers/FeedController.php CHANGED
@@ -7,7 +7,11 @@ class Businessfactory_Roihuntereasy_FeedController extends Mage_Core_Controller_
7
  Mage::log("Get product feed called.", null, 'feed.log');
8
 
9
  try {
10
- $file = "feeds/roi_hunter_easy_feed_final.xml";
 
 
 
 
11
 
12
  if (file_exists($file)) {
13
  header('Content-Description: File Transfer');
7
  Mage::log("Get product feed called.", null, 'feed.log');
8
 
9
  try {
10
+ $format = $this->getRequest()->getParam("format");
11
+ if (!isset($format) || trim($format)==='') {
12
+ $format = "xml";
13
+ }
14
+ $file = "feeds/roi_hunter_easy_feed_final." . $format;
15
 
16
  if (file_exists($file)) {
17
  header('Content-Description: File Transfer');
app/code/community/Businessfactory/Roihuntereasy/controllers/StoredetailsController.php CHANGED
@@ -8,6 +8,14 @@ class Businessfactory_Roihuntereasy_StoredetailsController extends Mage_Core_Con
8
  $this->renderLayout();
9
  }
10
 
 
 
 
 
 
 
 
 
11
  /**
12
  * http://store.com/roihuntereasy/storedetails/check
13
  */
@@ -15,14 +23,8 @@ class Businessfactory_Roihuntereasy_StoredetailsController extends Mage_Core_Con
15
  {
16
  Mage::log(__METHOD__ . "- Check called.");
17
 
18
- $request = $this->getRequest();
19
  $response = $this->getResponse();
20
-
21
- $response->setHeader('Content-type', 'application/json');
22
- $response->setHeader('Access-Control-Allow-Origin', '*', true);
23
- $response->setHeader('Access-Control-Allow-Methods', 'OPTIONS,GET,POST', true);
24
- $response->setHeader('Access-Control-Max-Age', '60', true);
25
- $response->setHeader('Access-Control-Allow-Headers', 'X-Authorization', true);
26
 
27
  $response->setBody(json_encode("rh-easy-active."));
28
  }
@@ -36,14 +38,9 @@ class Businessfactory_Roihuntereasy_StoredetailsController extends Mage_Core_Con
36
 
37
  $request = $this->getRequest();
38
  $response = $this->getResponse();
 
39
 
40
- $response->setHeader('Content-type', 'application/json');
41
- $response->setHeader('Access-Control-Allow-Origin', '*', true);
42
- $response->setHeader('Access-Control-Allow-Methods', 'OPTIONS,GET,POST', true);
43
- $response->setHeader('Access-Control-Max-Age', '60', true);
44
- $response->setHeader('Access-Control-Allow-Headers', 'X-Authorization', true);
45
-
46
- if ($request->getMethod() === 'GET') {
47
  $this->processDebugGET();
48
  }
49
  }
@@ -60,9 +57,9 @@ class Businessfactory_Roihuntereasy_StoredetailsController extends Mage_Core_Con
60
 
61
  try {
62
  // If table not empty, require authorization.
63
- $mainItemCollection = Mage::getModel('businessfactory_roihuntereasy/main')->getCollection();
64
  if ($mainItemCollection->count() > 0) {
65
- $authorizationHeader = $this->getRequest()->getHeader('X-Authorization');
66
  $dataEntity = $mainItemCollection->getLastItem();
67
  // If data exist check for client token.
68
  if ($dataEntity->getClientToken() != null && $dataEntity->getClientToken() !== $authorizationHeader) {
@@ -73,16 +70,16 @@ class Businessfactory_Roihuntereasy_StoredetailsController extends Mage_Core_Con
73
  }
74
 
75
  $resultData = $_SERVER;
76
- $resultData['Magento_Mode'] = Mage::getIsDeveloperMode() ? "developer" : "production";;
77
- $resultData['PHP_Version'] = phpversion();
78
- $resultData['Magento_Version'] = Mage::getVersion();
79
- $resultData['ROI_Hunter_Easy_Version'] = (string) Mage::getConfig()->getNode()->modules->Businessfactory_Roihuntereasy->version;
80
 
81
  $response->setBody(json_encode($resultData));
82
  } catch (Exception $exception) {
83
- Mage::log(__METHOD__ . " exception.", null, 'errors.log');
84
- Mage::log($exception, null, 'errors.log');
85
- Mage::log($request, null, 'errors.log');
86
  $response->setHttpResponseCode(500);
87
  }
88
  }
@@ -92,18 +89,13 @@ class Businessfactory_Roihuntereasy_StoredetailsController extends Mage_Core_Con
92
  */
93
  public function logsAction()
94
  {
95
- Mage::log(__METHOD__ . "- Debug called.", 'debug.log');
96
 
97
  $request = $this->getRequest();
98
  $response = $this->getResponse();
 
99
 
100
- $response->setHeader('Content-type', 'application/json');
101
- $response->setHeader('Access-Control-Allow-Origin', '*', true);
102
- $response->setHeader('Access-Control-Allow-Methods', 'OPTIONS,GET,POST', true);
103
- $response->setHeader('Access-Control-Max-Age', '60', true);
104
- $response->setHeader('Access-Control-Allow-Headers', 'X-Authorization', true);
105
-
106
- if ($request->getMethod() === 'GET') {
107
  $this->processLogsGET();
108
  }
109
  }
@@ -120,9 +112,9 @@ class Businessfactory_Roihuntereasy_StoredetailsController extends Mage_Core_Con
120
 
121
  try {
122
  // If table not empty, require authorization.
123
- $mainItemCollection = Mage::getModel('businessfactory_roihuntereasy/main')->getCollection();
124
  if ($mainItemCollection->count() > 0) {
125
- $authorizationHeader = $this->getRequest()->getHeader('X-Authorization');
126
  $dataEntity = $mainItemCollection->getLastItem();
127
  // If data exist check for client token.
128
  if ($dataEntity->getClientToken() != null && $dataEntity->getClientToken() !== $authorizationHeader) {
@@ -133,8 +125,8 @@ class Businessfactory_Roihuntereasy_StoredetailsController extends Mage_Core_Con
133
  }
134
 
135
  $zipFilename = "all_logs.zip";
136
- $rootPath = Mage::getBaseDir('log');
137
- $zipAbsolutePath = $rootPath . '/' . $zipFilename;
138
 
139
 
140
  $zip = new ZipArchive();
@@ -154,35 +146,35 @@ class Businessfactory_Roihuntereasy_StoredetailsController extends Mage_Core_Con
154
 
155
  foreach ($files as $name => $file) {
156
  // Skip directories (they would be added automatically)
157
- if (!$file->isDir() && strpos($file->getFilename(), 'all_logs.zip') === false) {
158
  // Get real and relative path for current file
159
  $filePath = $file->getRealPath();
160
  $relativePath = substr($filePath, strlen($rootPath));
161
  // Add current file to archive
162
  if ($zip->addFile($filePath, $relativePath) !== true) {
163
- Mage::log("cannot add file to zip", null, 'cro.log');
164
  $response->setBody("cannot add file to zip");
165
  return;
166
  }
167
  else {
168
- Mage::log("added file to zip", null, 'cro.log');
169
  }
170
  }
171
  }
172
  // Zip archive will be created only after closing object
173
  $zip->close();
174
 
175
- header('Content-Description: File Transfer');
176
- header('Content-Type: application/octet-stream');
177
- header('Content-Disposition: attachment; filename="' . basename($zipAbsolutePath) .'"');
178
- header('Expires: 0');
179
- header('Cache-Control: must-revalidate');
180
- header('Pragma: public');
181
  readfile($zipAbsolutePath);
182
  } catch (Exception $exception) {
183
- Mage::log(__METHOD__ . " exception.", null, 'errors.log');
184
- Mage::log($exception, null, 'errors.log');
185
- Mage::log($request, null, 'errors.log');
186
  $response->setHttpResponseCode(500);
187
  }
188
  }
@@ -194,16 +186,11 @@ class Businessfactory_Roihuntereasy_StoredetailsController extends Mage_Core_Con
194
  {
195
  $request = $this->getRequest();
196
  $response = $this->getResponse();
 
197
 
198
- $response->setHeader('Content-type', 'application/json');
199
- $response->setHeader('Access-Control-Allow-Origin', '*', true);
200
- $response->setHeader('Access-Control-Allow-Methods', 'OPTIONS,GET,POST', true);
201
- $response->setHeader('Access-Control-Max-Age', '60', true);
202
- $response->setHeader('Access-Control-Allow-Headers', 'X-Authorization', true);
203
-
204
- if ($request->getMethod() === 'GET') {
205
  $this->processStateGET();
206
- } else if ($request->getMethod() === 'POST') {
207
  $this->processStatePOST();
208
  }
209
  }
@@ -220,7 +207,7 @@ class Businessfactory_Roihuntereasy_StoredetailsController extends Mage_Core_Con
220
  $response = $this->getResponse();
221
 
222
  try {
223
- $mainItemCollection = Mage::getModel('businessfactory_roihuntereasy/main')->getCollection();
224
  // If table empty, then create new item.
225
  if ($mainItemCollection->count() <= 0) {
226
  $response->setBody(json_encode("Entry not exist."));
@@ -229,9 +216,9 @@ class Businessfactory_Roihuntereasy_StoredetailsController extends Mage_Core_Con
229
  $response->setBody(json_encode($mainItemCollection->getLastItem()->getCreationState()));
230
  }
231
  } catch (Exception $exception) {
232
- Mage::log(__METHOD__ . " exception.", null, 'errors.log');
233
- Mage::log($exception, null, 'errors.log');
234
- Mage::log($request, null, 'errors.log');
235
  $response->setHttpResponseCode(500);
236
  }
237
  }
@@ -250,8 +237,8 @@ class Businessfactory_Roihuntereasy_StoredetailsController extends Mage_Core_Con
250
  try {
251
  // Get request params
252
  $requestData = $request->getParams();
253
- $authorizationHeader = $request->getHeader('X-Authorization');
254
- $newCreationState = $request->getParam('new_state');
255
 
256
  if ($newCreationState === NULL) {
257
  $response->setBody(json_encode("Missing parameter."));
@@ -259,12 +246,12 @@ class Businessfactory_Roihuntereasy_StoredetailsController extends Mage_Core_Con
259
  return;
260
  } else {
261
  // Prepare database item. If table empty, then create new item.
262
- $mainItemCollection = Mage::getModel('businessfactory_roihuntereasy/main')->getCollection();
263
  if ($mainItemCollection->count() <= 0) {
264
- $dataEntity = Mage::getModel('businessfactory_roihuntereasy/main');
265
  $dataEntity->setDescription("New");
266
  } else {
267
- $dataEntity = Mage::getModel('businessfactory_roihuntereasy/main')->load($mainItemCollection->getLastItem()->getId());
268
  $dataEntity->setDescription("Updated");
269
 
270
  // If data already exist check for client token.
@@ -284,9 +271,9 @@ class Businessfactory_Roihuntereasy_StoredetailsController extends Mage_Core_Con
284
  )));
285
  }
286
  } catch (Exception $exception) {
287
- Mage::log(__METHOD__ . " exception.", null, 'errors.log');
288
- Mage::log($exception, null, 'errors.log');
289
- Mage::log($request, null, 'errors.log');
290
  $response->setHttpResponseCode(500);
291
  }
292
  }
@@ -298,16 +285,11 @@ class Businessfactory_Roihuntereasy_StoredetailsController extends Mage_Core_Con
298
  {
299
  $request = $this->getRequest();
300
  $response = $this->getResponse();
 
301
 
302
- $response->setHeader('Content-type', 'application/json');
303
- $response->setHeader('Access-Control-Allow-Origin', '*', true);
304
- $response->setHeader('Access-Control-Allow-Methods', 'OPTIONS,GET,POST', true);
305
- $response->setHeader('Access-Control-Max-Age', '60', true);
306
- $response->setHeader('Access-Control-Allow-Headers', 'X-Authorization', true);
307
-
308
- if ($request->getMethod() === 'GET') {
309
  $this->processAddGET();
310
- } else if ($request->getMethod() === 'POST') {
311
  $this->processAddPOST();
312
  }
313
  }
@@ -324,8 +306,8 @@ class Businessfactory_Roihuntereasy_StoredetailsController extends Mage_Core_Con
324
  $response = $this->getResponse();
325
 
326
  try {
327
- $mainItemCollection = Mage::getModel('businessfactory_roihuntereasy/main')->getCollection();
328
- $authorizationHeader = $this->getRequest()->getHeader('X-Authorization');
329
 
330
  // If table empty, then create new item.
331
  if ($mainItemCollection->count() <= 0) {
@@ -342,9 +324,9 @@ class Businessfactory_Roihuntereasy_StoredetailsController extends Mage_Core_Con
342
  $response->setBody(json_encode($dataEntity->getData()));
343
  }
344
  } catch (Exception $exception) {
345
- Mage::log(__METHOD__ . " exception.", null, 'errors.log');
346
- Mage::log($exception, null, 'errors.log');
347
- Mage::log($request, null, 'errors.log');
348
  $response->setHttpResponseCode(500);
349
  }
350
  }
@@ -363,18 +345,18 @@ class Businessfactory_Roihuntereasy_StoredetailsController extends Mage_Core_Con
363
  try {
364
  // Get request params
365
  $requestData = $request->getParams();
366
- Mage::log("Process add request with data: ", null, 'api.log');
367
- Mage::log($requestData, null, 'api.log');
368
 
369
- $authorizationHeader = $request->getHeader('X-Authorization');
370
 
371
  // Prepare database item. If table empty, then create new item.
372
- $mainItemCollection = Mage::getModel('businessfactory_roihuntereasy/main')->getCollection();
373
  if ($mainItemCollection->count() <= 0) {
374
- $dataEntity = Mage::getModel('businessfactory_roihuntereasy/main');
375
  $dataEntity->setDescription("New");
376
  } else {
377
- $dataEntity = Mage::getModel('businessfactory_roihuntereasy/main')->load($mainItemCollection->getLastItem()->getId());
378
  $dataEntity->setDescription("Updated");
379
 
380
  // If data already exist check for client token.
@@ -387,7 +369,7 @@ class Businessfactory_Roihuntereasy_StoredetailsController extends Mage_Core_Con
387
 
388
  // Save clientToken only if not exist
389
  if ($dataEntity->getClientToken() == NULL) {
390
- $client_token = $request->getParam('client_token');
391
  if ($client_token == NULL) {
392
  $response->setBody(json_encode("Missing client token"));
393
  $response->setHttpResponseCode(422);
@@ -399,7 +381,7 @@ class Businessfactory_Roihuntereasy_StoredetailsController extends Mage_Core_Con
399
 
400
  // Save AccessToken only if not exist
401
  if ($dataEntity->getAccessToken() == NULL) {
402
- $goostav_access_token = $request->getParam('access_token');
403
  if ($goostav_access_token == NULL) {
404
  $response->setBody(json_encode("Missing tokens"));
405
  $response->setHttpResponseCode(422);
@@ -411,32 +393,34 @@ class Businessfactory_Roihuntereasy_StoredetailsController extends Mage_Core_Con
411
 
412
 
413
  // Save status and errors if something failed
414
- $status = $request->getParam('status');
415
  if ($status != NULL) $dataEntity->setStatus($status);
416
- $errors = $request->getParam('errors');
417
  if ($errors != NULL) $dataEntity->setErrors($errors);
418
 
419
 
420
  // Save customer id
421
- $customerId = $request->getParam('id');
422
  if ($customerId != NULL) $dataEntity->setCustomerId($customerId);
423
  // Save conversion id
424
- $conversionId = $request->getParam('conversion_id');
425
  if ($conversionId != NULL) $dataEntity->setConversionId($conversionId);
426
 
427
  // Set managed merchants
428
- $managedMerchants = $request->getParam('managed_merchants');
429
- if ($managedMerchants !== NULL) $dataEntity->setManagedMerchants($managedMerchants === 'true');
430
  // Set adult content
431
- $adultOriented = $request->getParam('adult_oriented');
432
- if ($adultOriented !== NULL) $dataEntity->setAdultOriented($adultOriented === 'true');
433
-
 
 
434
 
435
  // Persist data
436
  $dataEntity->save();
437
 
438
  // Create verification file
439
- $filename = $request->getParam('site_verification_token');
440
  $this->createVerificationFile($filename);
441
 
442
  // Return response
@@ -444,9 +428,9 @@ class Businessfactory_Roihuntereasy_StoredetailsController extends Mage_Core_Con
444
  "data" => $requestData
445
  )));
446
  } catch (Exception $exception) {
447
- Mage::log(__METHOD__ . " exception.", null, 'errors.log');
448
- Mage::log($exception, null, 'errors.log');
449
- Mage::log($request, null, 'errors.log');
450
  $response->setHttpResponseCode(500);
451
  }
452
  }
@@ -463,7 +447,7 @@ class Businessfactory_Roihuntereasy_StoredetailsController extends Mage_Core_Con
463
  // Apache
464
  $io = new Varien_Io_File();
465
  $io->setAllowCreateFolders(true);
466
- $io->open(array('path' => Mage::getBaseDir()));
467
 
468
  if ($io->fileExists($filename)) {
469
  $io->rm($filename);
@@ -476,11 +460,11 @@ class Businessfactory_Roihuntereasy_StoredetailsController extends Mage_Core_Con
476
  // Nginx - check if it is necessary to create file in public folder
477
 
478
  } else {
479
- Mage::log('ERROR: Cannot create verification file. Missing filename', null, 'errors.log');
480
  }
481
  } catch (Exception $exception) {
482
- Mage::log(__METHOD__ . " exception.", null, 'errors.log');
483
- Mage::log($exception, null, 'errors.log');
484
  }
485
  }
486
  }
8
  $this->renderLayout();
9
  }
10
 
11
+ protected function setResponseHeaders(& $response) {
12
+ $response->setHeader("Content-type", "application/json");
13
+ $response->setHeader("Access-Control-Allow-Origin", "*", true);
14
+ $response->setHeader("Access-Control-Allow-Methods", "OPTIONS,GET,POST", true);
15
+ $response->setHeader("Access-Control-Max-Age", "60", true);
16
+ $response->setHeader("Access-Control-Allow-Headers", "X-Authorization", true);
17
+ }
18
+
19
  /**
20
  * http://store.com/roihuntereasy/storedetails/check
21
  */
23
  {
24
  Mage::log(__METHOD__ . "- Check called.");
25
 
 
26
  $response = $this->getResponse();
27
+ $this->setResponseHeaders($response);
 
 
 
 
 
28
 
29
  $response->setBody(json_encode("rh-easy-active."));
30
  }
38
 
39
  $request = $this->getRequest();
40
  $response = $this->getResponse();
41
+ $this->setResponseHeaders($response);
42
 
43
+ if ($request->getMethod() === "GET") {
 
 
 
 
 
 
44
  $this->processDebugGET();
45
  }
46
  }
57
 
58
  try {
59
  // If table not empty, require authorization.
60
+ $mainItemCollection = Mage::getModel("businessfactory_roihuntereasy/main")->getCollection();
61
  if ($mainItemCollection->count() > 0) {
62
+ $authorizationHeader = $this->getRequest()->getHeader("X-Authorization");
63
  $dataEntity = $mainItemCollection->getLastItem();
64
  // If data exist check for client token.
65
  if ($dataEntity->getClientToken() != null && $dataEntity->getClientToken() !== $authorizationHeader) {
70
  }
71
 
72
  $resultData = $_SERVER;
73
+ $resultData["Magento_Mode"] = Mage::getIsDeveloperMode() ? "developer" : "production";;
74
+ $resultData["PHP_Version"] = phpversion();
75
+ $resultData["Magento_Version"] = Mage::getVersion();
76
+ $resultData["ROI_Hunter_Easy_Version"] = (string) Mage::getConfig()->getNode()->modules->Businessfactory_Roihuntereasy->version;
77
 
78
  $response->setBody(json_encode($resultData));
79
  } catch (Exception $exception) {
80
+ Mage::log(__METHOD__ . " exception.", null, "errors.log");
81
+ Mage::log($exception, null, "errors.log");
82
+ Mage::log($request, null, "errors.log");
83
  $response->setHttpResponseCode(500);
84
  }
85
  }
89
  */
90
  public function logsAction()
91
  {
92
+ Mage::log(__METHOD__ . "- Debug called.", "debug.log");
93
 
94
  $request = $this->getRequest();
95
  $response = $this->getResponse();
96
+ $this->setResponseHeaders($response);
97
 
98
+ if ($request->getMethod() === "GET") {
 
 
 
 
 
 
99
  $this->processLogsGET();
100
  }
101
  }
112
 
113
  try {
114
  // If table not empty, require authorization.
115
+ $mainItemCollection = Mage::getModel("businessfactory_roihuntereasy/main")->getCollection();
116
  if ($mainItemCollection->count() > 0) {
117
+ $authorizationHeader = $this->getRequest()->getHeader("X-Authorization");
118
  $dataEntity = $mainItemCollection->getLastItem();
119
  // If data exist check for client token.
120
  if ($dataEntity->getClientToken() != null && $dataEntity->getClientToken() !== $authorizationHeader) {
125
  }
126
 
127
  $zipFilename = "all_logs.zip";
128
+ $rootPath = Mage::getBaseDir("log");
129
+ $zipAbsolutePath = $rootPath . "/" . $zipFilename;
130
 
131
 
132
  $zip = new ZipArchive();
146
 
147
  foreach ($files as $name => $file) {
148
  // Skip directories (they would be added automatically)
149
+ if (!$file->isDir() && strpos($file->getFilename(), "all_logs.zip") === false) {
150
  // Get real and relative path for current file
151
  $filePath = $file->getRealPath();
152
  $relativePath = substr($filePath, strlen($rootPath));
153
  // Add current file to archive
154
  if ($zip->addFile($filePath, $relativePath) !== true) {
155
+ Mage::log("cannot add file to zip", null, "cro.log");
156
  $response->setBody("cannot add file to zip");
157
  return;
158
  }
159
  else {
160
+ Mage::log("added file to zip", null, "cro.log");
161
  }
162
  }
163
  }
164
  // Zip archive will be created only after closing object
165
  $zip->close();
166
 
167
+ header("Content-Description: File Transfer");
168
+ header("Content-Type: application/octet-stream");
169
+ header("Content-Disposition: attachment; filename='" . basename($zipAbsolutePath) ."'");
170
+ header("Expires: 0");
171
+ header("Cache-Control: must-revalidate");
172
+ header("Pragma: public");
173
  readfile($zipAbsolutePath);
174
  } catch (Exception $exception) {
175
+ Mage::log(__METHOD__ . " exception.", null, "errors.log");
176
+ Mage::log($exception, null, "errors.log");
177
+ Mage::log($request, null, "errors.log");
178
  $response->setHttpResponseCode(500);
179
  }
180
  }
186
  {
187
  $request = $this->getRequest();
188
  $response = $this->getResponse();
189
+ $this->setResponseHeaders($response);
190
 
191
+ if ($request->getMethod() === "GET") {
 
 
 
 
 
 
192
  $this->processStateGET();
193
+ } else if ($request->getMethod() === "POST") {
194
  $this->processStatePOST();
195
  }
196
  }
207
  $response = $this->getResponse();
208
 
209
  try {
210
+ $mainItemCollection = Mage::getModel("businessfactory_roihuntereasy/main")->getCollection();
211
  // If table empty, then create new item.
212
  if ($mainItemCollection->count() <= 0) {
213
  $response->setBody(json_encode("Entry not exist."));
216
  $response->setBody(json_encode($mainItemCollection->getLastItem()->getCreationState()));
217
  }
218
  } catch (Exception $exception) {
219
+ Mage::log(__METHOD__ . " exception.", null, "errors.log");
220
+ Mage::log($exception, null, "errors.log");
221
+ Mage::log($request, null, "errors.log");
222
  $response->setHttpResponseCode(500);
223
  }
224
  }
237
  try {
238
  // Get request params
239
  $requestData = $request->getParams();
240
+ $authorizationHeader = $request->getHeader("X-Authorization");
241
+ $newCreationState = $request->getParam("new_state");
242
 
243
  if ($newCreationState === NULL) {
244
  $response->setBody(json_encode("Missing parameter."));
246
  return;
247
  } else {
248
  // Prepare database item. If table empty, then create new item.
249
+ $mainItemCollection = Mage::getModel("businessfactory_roihuntereasy/main")->getCollection();
250
  if ($mainItemCollection->count() <= 0) {
251
+ $dataEntity = Mage::getModel("businessfactory_roihuntereasy/main");
252
  $dataEntity->setDescription("New");
253
  } else {
254
+ $dataEntity = Mage::getModel("businessfactory_roihuntereasy/main")->load($mainItemCollection->getLastItem()->getId());
255
  $dataEntity->setDescription("Updated");
256
 
257
  // If data already exist check for client token.
271
  )));
272
  }
273
  } catch (Exception $exception) {
274
+ Mage::log(__METHOD__ . " exception.", null, "errors.log");
275
+ Mage::log($exception, null, "errors.log");
276
+ Mage::log($request, null, "errors.log");
277
  $response->setHttpResponseCode(500);
278
  }
279
  }
285
  {
286
  $request = $this->getRequest();
287
  $response = $this->getResponse();
288
+ $this->setResponseHeaders($response);
289
 
290
+ if ($request->getMethod() === "GET") {
 
 
 
 
 
 
291
  $this->processAddGET();
292
+ } else if ($request->getMethod() === "POST") {
293
  $this->processAddPOST();
294
  }
295
  }
306
  $response = $this->getResponse();
307
 
308
  try {
309
+ $mainItemCollection = Mage::getModel("businessfactory_roihuntereasy/main")->getCollection();
310
+ $authorizationHeader = $this->getRequest()->getHeader("X-Authorization");
311
 
312
  // If table empty, then create new item.
313
  if ($mainItemCollection->count() <= 0) {
324
  $response->setBody(json_encode($dataEntity->getData()));
325
  }
326
  } catch (Exception $exception) {
327
+ Mage::log(__METHOD__ . " exception.", null, "errors.log");
328
+ Mage::log($exception, null, "errors.log");
329
+ Mage::log($request, null, "errors.log");
330
  $response->setHttpResponseCode(500);
331
  }
332
  }
345
  try {
346
  // Get request params
347
  $requestData = $request->getParams();
348
+ Mage::log("Process add request with data: ", null, "debug.log");
349
+ Mage::log(json_encode($requestData), null, "debug.log");
350
 
351
+ $authorizationHeader = $request->getHeader("X-Authorization");
352
 
353
  // Prepare database item. If table empty, then create new item.
354
+ $mainItemCollection = Mage::getModel("businessfactory_roihuntereasy/main")->getCollection();
355
  if ($mainItemCollection->count() <= 0) {
356
+ $dataEntity = Mage::getModel("businessfactory_roihuntereasy/main");
357
  $dataEntity->setDescription("New");
358
  } else {
359
+ $dataEntity = Mage::getModel("businessfactory_roihuntereasy/main")->load($mainItemCollection->getLastItem()->getId());
360
  $dataEntity->setDescription("Updated");
361
 
362
  // If data already exist check for client token.
369
 
370
  // Save clientToken only if not exist
371
  if ($dataEntity->getClientToken() == NULL) {
372
+ $client_token = $request->getParam("client_token");
373
  if ($client_token == NULL) {
374
  $response->setBody(json_encode("Missing client token"));
375
  $response->setHttpResponseCode(422);
381
 
382
  // Save AccessToken only if not exist
383
  if ($dataEntity->getAccessToken() == NULL) {
384
+ $goostav_access_token = $request->getParam("access_token");
385
  if ($goostav_access_token == NULL) {
386
  $response->setBody(json_encode("Missing tokens"));
387
  $response->setHttpResponseCode(422);
393
 
394
 
395
  // Save status and errors if something failed
396
+ $status = $request->getParam("status");
397
  if ($status != NULL) $dataEntity->setStatus($status);
398
+ $errors = $request->getParam("errors");
399
  if ($errors != NULL) $dataEntity->setErrors($errors);
400
 
401
 
402
  // Save customer id
403
+ $customerId = $request->getParam("id");
404
  if ($customerId != NULL) $dataEntity->setCustomerId($customerId);
405
  // Save conversion id
406
+ $conversionId = $request->getParam("conversion_id");
407
  if ($conversionId != NULL) $dataEntity->setConversionId($conversionId);
408
 
409
  // Set managed merchants
410
+ $managedMerchants = $request->getParam("managed_merchants");
411
+ if ($managedMerchants !== NULL) $dataEntity->setManagedMerchants($managedMerchants === "true");
412
  // Set adult content
413
+ $adultOriented = $request->getParam("adult_oriented");
414
+ if ($adultOriented !== NULL) $dataEntity->setAdultOriented($adultOriented === "true");
415
+ // Set conversion label
416
+ $conversionLabel = $request->getParam("conversion_label");
417
+ if ($conversionLabel !== NULL) $dataEntity->setConversionLabel($conversionLabel);
418
 
419
  // Persist data
420
  $dataEntity->save();
421
 
422
  // Create verification file
423
+ $filename = $request->getParam("site_verification_token");
424
  $this->createVerificationFile($filename);
425
 
426
  // Return response
428
  "data" => $requestData
429
  )));
430
  } catch (Exception $exception) {
431
+ Mage::log(__METHOD__ . " exception.", null, "errors.log");
432
+ Mage::log($exception, null, "errors.log");
433
+ Mage::log($request, null, "errors.log");
434
  $response->setHttpResponseCode(500);
435
  }
436
  }
447
  // Apache
448
  $io = new Varien_Io_File();
449
  $io->setAllowCreateFolders(true);
450
+ $io->open(array("path" => Mage::getBaseDir()));
451
 
452
  if ($io->fileExists($filename)) {
453
  $io->rm($filename);
460
  // Nginx - check if it is necessary to create file in public folder
461
 
462
  } else {
463
+ Mage::log("ERROR: Cannot create verification file. Missing filename", null, "errors.log");
464
  }
465
  } catch (Exception $exception) {
466
+ Mage::log(__METHOD__ . " exception.", null, "errors.log");
467
+ Mage::log($exception, null, "errors.log");
468
  }
469
  }
470
  }
app/code/community/Businessfactory/Roihuntereasy/etc/config.xml CHANGED
@@ -2,7 +2,7 @@
2
  <config>
3
  <modules>
4
  <Businessfactory_Roihuntereasy>
5
- <version>1.0.9</version>
6
  </Businessfactory_Roihuntereasy>
7
  </modules>
8
  <admin>
@@ -118,10 +118,16 @@
118
  </global>
119
  <crontab>
120
  <jobs>
121
- <businessfactory_roihuntereasy>
122
- <schedule><cron_expr>*/15 * * * *</cron_expr></schedule>
123
- <run><model>businessfactory_roihuntereasy/cron::createFeed</model></run>
124
- </businessfactory_roihuntereasy>
 
 
 
 
 
 
125
  </jobs>
126
  </crontab>
127
  </config>
2
  <config>
3
  <modules>
4
  <Businessfactory_Roihuntereasy>
5
+ <version>1.1.0</version>
6
  </Businessfactory_Roihuntereasy>
7
  </modules>
8
  <admin>
118
  </global>
119
  <crontab>
120
  <jobs>
121
+ <businessfactory_roihuntereasy_xml>
122
+ <schedule><cron_expr>0 */2 * * *</cron_expr></schedule>
123
+ <run><model>businessfactory_roihuntereasy/cron::scheduleFeed</model></run>
124
+ <format>xml</format>
125
+ </businessfactory_roihuntereasy_xml>
126
+ <businessfactory_roihuntereasy_csv>
127
+ <schedule><cron_expr>0 */2 * * *</cron_expr></schedule>
128
+ <run><model>businessfactory_roihuntereasy/cron::scheduleFeed</model></run>
129
+ <format>csv</format>
130
+ </businessfactory_roihuntereasy_csv>
131
  </jobs>
132
  </crontab>
133
  </config>
app/code/community/Businessfactory/Roihuntereasy/sql/businessfactory_roihuntereasy_setup/{install-1.0.0.php → install-1.0.9.php} RENAMED
File without changes
app/code/community/Businessfactory/Roihuntereasy/sql/businessfactory_roihuntereasy_setup/upgrade-1.0.9-1.1.0.php ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ $installer = $this;
4
+ $connection = $installer->getConnection();
5
+
6
+ $installer->startSetup();
7
+
8
+ $installer->getConnection()
9
+ ->addColumn($installer->getTable('businessfactory_roihuntereasy/main'),
10
+ 'conversion_label',
11
+ array(
12
+ 'type' => Varien_Db_Ddl_Table::TYPE_TEXT, 255,
13
+ 'nullable' => true,
14
+ 'default' => null,
15
+ 'length' => 255,
16
+ 'comment' => 'Conversion Label'
17
+ )
18
+ );
19
+
20
+ $installer->endSetup();
app/design/adminhtml/default/default/template/businessfactory_roihuntereasy/admin.phtml CHANGED
@@ -16,6 +16,7 @@
16
  var creationState = "<?php echo($this->getMainItemEntry() ? $this->getMainItemEntry()->getCreationState() : null); ?>";
17
  var magentoMode = "<?php echo $this->getDevelopmentMode(); ?>";
18
  var pluginVersion = "magento_" + "<?php echo $this->getPluginVersion(); ?>";
 
19
 
20
  console.log("mode: " + magentoMode);
21
  console.log("baseUrl: " + storeUrl);
@@ -31,6 +32,7 @@
31
  "storeCountry": storeCountry,
32
  "storeMode": magentoMode,
33
  "pluginVersion": pluginVersion,
 
34
 
35
  // Database part
36
  "customerId": customerId,
@@ -63,7 +65,7 @@
63
  </script>
64
 
65
  <!--"http://localhost:3000" "http://magento.roihunter.com/" -->
66
- <iframe src="//magento.roihunter.com/"
67
  id="RoiHunterEasyIFrame"
68
  scrolling="yes"
69
  frameBorder="0"
16
  var creationState = "<?php echo($this->getMainItemEntry() ? $this->getMainItemEntry()->getCreationState() : null); ?>";
17
  var magentoMode = "<?php echo $this->getDevelopmentMode(); ?>";
18
  var pluginVersion = "magento_" + "<?php echo $this->getPluginVersion(); ?>";
19
+ var stagingActive = <?php echo json_encode($this->isStagingActive()); ?>;
20
 
21
  console.log("mode: " + magentoMode);
22
  console.log("baseUrl: " + storeUrl);
32
  "storeCountry": storeCountry,
33
  "storeMode": magentoMode,
34
  "pluginVersion": pluginVersion,
35
+ "stagingActive": stagingActive,
36
 
37
  // Database part
38
  "customerId": customerId,
65
  </script>
66
 
67
  <!--"http://localhost:3000" "http://magento.roihunter.com/" -->
68
+ <iframe src="<?php echo $this->getIframeBaseUrl(); ?>"
69
  id="RoiHunterEasyIFrame"
70
  scrolling="yes"
71
  frameBorder="0"
app/design/frontend/base/default/template/businessfactory_roihuntereasy/checkout_analytics.phtml CHANGED
@@ -3,6 +3,8 @@
3
  $_prodSku = $this->getProdId();
4
  $_prodPrice = $this->getProdPrice();
5
  $_conversionId = $this->getConversionId();
 
 
6
 
7
  ?>
8
 
@@ -15,7 +17,7 @@ Remarketing tags may not be associated with personally identifiable information
15
  var google_conversion_id = <?php echo $_conversionId ?>;
16
  var google_custom_params = {
17
  ecomm_prodid: <?php echo $_prodSku ?>,
18
- ecomm_pagetype: 'purchase',
19
  ecomm_totalvalue: <?php echo $_prodPrice ?>,
20
  };
21
  var google_remarketing_only = true;
@@ -36,7 +38,9 @@ Remarketing tags may not be associated with personally identifiable information
36
  var google_conversion_language = "en_US";
37
  var google_conversion_format = "1";
38
  var google_conversion_color = "666666";
39
- var google_remarketing_only = true;
 
 
40
  var google_conversion_value = <?php echo $_prodPrice ?>;
41
  /* ]]> */
42
  </script>
@@ -44,5 +48,5 @@ Remarketing tags may not be associated with personally identifiable information
44
  </script>
45
  <noscript>
46
  <img height=1 width=1 border=0 src="//www.googleadservices.com/pagead/
47
- conversion/<?php echo $_conversionId ?>/?value=<?php echo $_prodPrice ?>&amp;guid=ON&amp;script=0">
48
  </noscript>
3
  $_prodSku = $this->getProdId();
4
  $_prodPrice = $this->getProdPrice();
5
  $_conversionId = $this->getConversionId();
6
+ $_conversionLabel = $this->getConversionLabel();
7
+ $_currency = $this->getConversionCurrency();
8
 
9
  ?>
10
 
17
  var google_conversion_id = <?php echo $_conversionId ?>;
18
  var google_custom_params = {
19
  ecomm_prodid: <?php echo $_prodSku ?>,
20
+ ecomm_pagetype: "purchase",
21
  ecomm_totalvalue: <?php echo $_prodPrice ?>,
22
  };
23
  var google_remarketing_only = true;
38
  var google_conversion_language = "en_US";
39
  var google_conversion_format = "1";
40
  var google_conversion_color = "666666";
41
+ var google_conversion_label = "<?php echo $_conversionLabel ?>";
42
+ var google_conversion_currency = "<?php echo $_currency ?>";
43
+ var google_remarketing_only = false;
44
  var google_conversion_value = <?php echo $_prodPrice ?>;
45
  /* ]]> */
46
  </script>
48
  </script>
49
  <noscript>
50
  <img height=1 width=1 border=0 src="//www.googleadservices.com/pagead/
51
+ conversion/<?php echo $_conversionId ?>/?value=<?php echo $_prodPrice ?>&amp;currency_code=<?php echo $_currency ?>&amp;label=<?php echo $_conversionLabel ?>&amp;guid=ON&amp;script=0">
52
  </noscript>
package.xml CHANGED
@@ -1,7 +1,7 @@
1
  <?xml version="1.0"?>
2
  <package>
3
  <name>roihunter_easy</name>
4
- <version>1.0.9</version>
5
  <stability>stable</stability>
6
  <license>AFL 3.0</license>
7
  <channel>community</channel>
@@ -40,11 +40,11 @@ Extension update: 0.00 &amp;#x20AC;&amp;#xD;&#xD;
40
  No support fee&amp;#xD;&#xD;
41
  No contract duration&amp;#xD;&#xD;
42
  * Extension do not cover your Google Adwords Ad Spend. </description>
43
- <notes>Created 5th April, 2017 Compatibility: 1.9.2.4 - Product feed improvements</notes>
44
  <authors><author><name>ROI Hunter</name><user>MAG003490427</user><email>petr.skornok@b.cz</email></author></authors>
45
- <date>2017-04-05</date>
46
- <time>12:55:49</time>
47
- <contents><target name="magecommunity"><dir name="Businessfactory"><dir name="Roihuntereasy"><dir name="Block"><file name="AddedToCartAnalytics.php" hash="eeb701f487b06ed82e0754aefb192fab"/><dir name="Adminhtml"><file name="Admin.php" hash="091758eba688f453d63463953c114faf"/><dir name="System"><dir name="Config"><file name="Cronbutton.php" hash="a07a6cfbd52a9a96fb4ec78cc8270924"/><file name="Resetbutton.php" hash="7721bb62feafe5d9d2951e70bfb0c30e"/></dir></dir></dir><file name="CategoryViewAnalytics.php" hash="8a47d9b4b0ad88c2e3fc1aa38258c465"/><file name="CheckoutAnalytics.php" hash="831094424cf896e6644d66b0c70c3688"/><file name="Database.php" hash="4333ce4f66b762097cb50b4f04a7a4d2"/><file name="ProductViewAnalytics.php" hash="033e6702927d92ae5f2d388f00b46bd5"/></dir><dir name="Helper"><file name="Data.php" hash="05ee8de6f74805d4a2b4643b0b0fe33a"/></dir><dir name="Model"><file name="AddedToCartObserver.php" hash="4e6d394f8f0902904e357f441aca6289"/><file name="CheckoutObserver.php" hash="2468bfbdf1083205a0e3aba14d2b7510"/><file name="Cron.php" hash="ae3a41efb92aca2ad23fc6710b1c3ac4"/><file name="Main.php" hash="06766b59391b52aaa701d8bf01e80d1a"/><file name="Options.php" hash="f6ecd5ab10cfcc5e0948b236bb873932"/><dir name="Resource"><dir name="Main"><file name="Collection.php" hash="9b66b73b312ac16e270c1435a789fdb9"/></dir><file name="Main.php" hash="1432c450ff554fb5057d1d6c4fd26c3c"/></dir></dir><dir name="controllers"><dir name="Adminhtml"><file name="RoihuntereasyController.php" hash="687380dafaffd792a281e2bfd653d027"/></dir><file name="CronController.php" hash="f160c324b60ce92b249731bb97aa1e75"/><file name="FeedController.php" hash="e185b7550c6ef091b5fbcf51f315dc5a"/><file name="IndexController.php" hash="33c2a22770591cbeb7fb394d3654d904"/><file name="ResetController.php" hash="1a6c578829957c0a2ec2a4085ed5a089"/><file name="RoihuntereasyController.php" hash="b2b37f613badb75be2198e6643ef8d85"/><file name="StoredetailsController.php" hash="9b1173503bec12f154dc7566c50227ce"/></dir><dir name="etc"><file name="adminhtml.xml" hash="bbab6af370448895030570a657469a15"/><file name="config.xml" hash="cc7543a088462e0a71aea3808e520977"/><file name="system.xml" hash="718ea25db00b6a500b8783f9c8e1ba5c"/></dir><dir name="sql"><dir name="businessfactory_roihuntereasy_setup"><file name="install-1.0.0.php" hash="f490ddfd229eb5680e68fb7ec55a5820"/></dir></dir></dir></dir></target><target name="magedesign"><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="layout"><file name="businessfactory_roihuntereasy.xml" hash="fa2e345d2461459e15c641731d1b114a"/></dir><dir name="template"><dir name="businessfactory_roihuntereasy"><file name="admin.phtml" hash="75f444e06a86afe1b111f9f8c5fb6904"/><dir name="system"><dir name="config"><file name="cronbutton.phtml" hash="758b97b5da81c92aaeb175e4b0142288"/><file name="resetbutton.phtml" hash="7aedce71c5d21bfce1a08c77e603143d"/></dir></dir></dir></dir></dir></dir></dir><dir name="frontend"><dir name="base"><dir name="default"><dir name="layout"><file name="businessfactory_roihuntereasy.xml" hash="e1379f4d0a022d6740d0a6d96fd9fbed"/></dir><dir name="template"><dir name="businessfactory_roihuntereasy"><file name="added_to_cart_view_analytics.phtml" hash="8679d7940136d046ce46d2bc9aa2b522"/><file name="category_view_analytics.phtml" hash="420fe9c183c444e655250efa0b037da4"/><file name="checkout_analytics.phtml" hash="f06507f3867d78e0e6f1791fc210797d"/><file name="index.phtml" hash="a69cff3727b7bba2be7154b94b86ff08"/><file name="product_view_analytics.phtml" hash="a9ce50a31d64edcc70b2bbabd2ebf227"/></dir></dir></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="Businessfactory_Roihuntereasy.xml" hash="d46e92b8a1b158bfdc47b9daa3274a3d"/></dir></target></contents>
48
  <compatible/>
49
  <dependencies><required><php><min>5.5.0</min><max>7.0.0</max></php></required></dependencies>
50
  </package>
1
  <?xml version="1.0"?>
2
  <package>
3
  <name>roihunter_easy</name>
4
+ <version>1.1.0</version>
5
  <stability>stable</stability>
6
  <license>AFL 3.0</license>
7
  <channel>community</channel>
40
  No support fee&amp;#xD;&#xD;
41
  No contract duration&amp;#xD;&#xD;
42
  * Extension do not cover your Google Adwords Ad Spend. </description>
43
+ <notes>Created 16th April, 2017 Compatibility: 1.9.2.4 - CSV Product feed for Adwords compatibility, Conversion tracking, Product feed images and sale price improvements</notes>
44
  <authors><author><name>ROI Hunter</name><user>MAG003490427</user><email>petr.skornok@b.cz</email></author></authors>
45
+ <date>2017-04-19</date>
46
+ <time>16:17:32</time>
47
+ <contents><target name="magecommunity"><dir name="Businessfactory"><dir name="Roihuntereasy"><dir name="Block"><file name="AddedToCartAnalytics.php" hash="eeb701f487b06ed82e0754aefb192fab"/><dir name="Adminhtml"><file name="Admin.php" hash="696ce1b1e1c03cb4d69bd547bb95396c"/><dir name="System"><dir name="Config"><file name="Cronbutton.php" hash="a07a6cfbd52a9a96fb4ec78cc8270924"/><file name="Resetbutton.php" hash="7721bb62feafe5d9d2951e70bfb0c30e"/></dir></dir></dir><file name="CategoryViewAnalytics.php" hash="8a47d9b4b0ad88c2e3fc1aa38258c465"/><file name="CheckoutAnalytics.php" hash="774200dbb45c1a3f832950b9c89d8557"/><file name="Database.php" hash="4333ce4f66b762097cb50b4f04a7a4d2"/><file name="ProductViewAnalytics.php" hash="033e6702927d92ae5f2d388f00b46bd5"/></dir><dir name="Helper"><file name="Data.php" hash="05ee8de6f74805d4a2b4643b0b0fe33a"/></dir><dir name="Model"><file name="AddedToCartObserver.php" hash="4e6d394f8f0902904e357f441aca6289"/><file name="CheckoutObserver.php" hash="8849a591a83dbd4e9aa7900c13176bb0"/><file name="Cron.php" hash="4ba20cd18f139d89a2ed30cdaf5ffb46"/><file name="Main.php" hash="06766b59391b52aaa701d8bf01e80d1a"/><file name="Options.php" hash="f6ecd5ab10cfcc5e0948b236bb873932"/><dir name="Resource"><dir name="Main"><file name="Collection.php" hash="9b66b73b312ac16e270c1435a789fdb9"/></dir><file name="Main.php" hash="1432c450ff554fb5057d1d6c4fd26c3c"/></dir></dir><dir name="controllers"><dir name="Adminhtml"><file name="RoihuntereasyController.php" hash="687380dafaffd792a281e2bfd653d027"/></dir><file name="CronController.php" hash="7fae1e9140232183349a25e1267192a0"/><file name="FeedController.php" hash="4d3bca0c750174772ec91b0da4cc4182"/><file name="IndexController.php" hash="33c2a22770591cbeb7fb394d3654d904"/><file name="ResetController.php" hash="1a6c578829957c0a2ec2a4085ed5a089"/><file name="RoihuntereasyController.php" hash="b2b37f613badb75be2198e6643ef8d85"/><file name="StoredetailsController.php" hash="5440a2526b90a4bea9b0bf20486ac2b0"/></dir><dir name="etc"><file name="adminhtml.xml" hash="bbab6af370448895030570a657469a15"/><file name="config.xml" hash="ccb69bc13d9921bc514b4d213aaf0575"/><file name="system.xml" hash="718ea25db00b6a500b8783f9c8e1ba5c"/></dir><dir name="sql"><dir name="businessfactory_roihuntereasy_setup"><file name="install-1.0.9.php" hash="f490ddfd229eb5680e68fb7ec55a5820"/><file name="upgrade-1.0.9-1.1.0.php" hash="9a3aa2942881aad0e386c6284c012b4c"/></dir></dir></dir></dir></target><target name="magedesign"><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="layout"><file name="businessfactory_roihuntereasy.xml" hash="fa2e345d2461459e15c641731d1b114a"/></dir><dir name="template"><dir name="businessfactory_roihuntereasy"><file name="admin.phtml" hash="5688c1f85088716c6f3e9ef8cbed49f2"/><dir name="system"><dir name="config"><file name="cronbutton.phtml" hash="758b97b5da81c92aaeb175e4b0142288"/><file name="resetbutton.phtml" hash="7aedce71c5d21bfce1a08c77e603143d"/></dir></dir></dir></dir></dir></dir></dir><dir name="frontend"><dir name="base"><dir name="default"><dir name="layout"><file name="businessfactory_roihuntereasy.xml" hash="e1379f4d0a022d6740d0a6d96fd9fbed"/></dir><dir name="template"><dir name="businessfactory_roihuntereasy"><file name="added_to_cart_view_analytics.phtml" hash="8679d7940136d046ce46d2bc9aa2b522"/><file name="category_view_analytics.phtml" hash="420fe9c183c444e655250efa0b037da4"/><file name="checkout_analytics.phtml" hash="65de844a372d10f6f215382c988dbe2a"/><file name="index.phtml" hash="a69cff3727b7bba2be7154b94b86ff08"/><file name="product_view_analytics.phtml" hash="a9ce50a31d64edcc70b2bbabd2ebf227"/></dir></dir></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="Businessfactory_Roihuntereasy.xml" hash="d46e92b8a1b158bfdc47b9daa3274a3d"/></dir></target></contents>
48
  <compatible/>
49
  <dependencies><required><php><min>5.5.0</min><max>7.0.0</max></php></required></dependencies>
50
  </package>