Version Notes
Added debug logging, category url to hierarchy file.
Download this release
Release Info
Developer | Hawksearch Inc. |
Extension | HawkSearch_Datafeed |
Version | 1.0.3.0 |
Comparing to | |
See all releases |
Code changes from version 1.0.0.2 to 1.0.3.0
- app/code/community/Hawksearch/Datafeed/Block/System/Config/Frontend/Feed/Clearts/Js.php +33 -0
- app/code/community/Hawksearch/Datafeed/Block/System/Config/Frontend/Feed/Generate/Js.php +6 -6
- app/code/community/Hawksearch/Datafeed/Block/System/Config/Frontend/Feed/Generateimagecache/Js.php +6 -6
- app/code/community/Hawksearch/Datafeed/Block/System/Config/Frontend/Feed/Timestamp.php +51 -0
- app/code/community/Hawksearch/Datafeed/Helper/Data.php +1 -1
- app/code/community/Hawksearch/Datafeed/Helper/Feed.php +37 -85
- app/code/community/Hawksearch/Datafeed/Helper/runfeed.php +33 -0
- app/code/community/Hawksearch/Datafeed/Model/Cron.php +1 -5
- app/code/community/Hawksearch/Datafeed/Model/Feed.php +274 -259
- app/code/community/Hawksearch/Datafeed/controllers/SearchController.php +32 -96
- app/code/community/Hawksearch/Datafeed/etc/config.xml +2 -17
- app/code/community/Hawksearch/Datafeed/etc/system.xml +0 -9
- app/design/adminhtml/default/default/template/hawksearch/datafeed/clearts/js.phtml +65 -0
- app/design/adminhtml/default/default/template/hawksearch/datafeed/generate/js.phtml +56 -0
- app/design/adminhtml/default/default/template/hawksearch/{search/sysconfig → datafeed}/generateimagecache/js.phtml +0 -0
- app/design/adminhtml/default/default/template/hawksearch/search/sysconfig/generate/js.phtml +0 -50
- package.xml +5 -7
app/code/community/Hawksearch/Datafeed/Block/System/Config/Frontend/Feed/Clearts/Js.php
ADDED
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) 2013 Hawksearch (www.hawksearch.com) - All Rights Reserved
|
4 |
+
*
|
5 |
+
* THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
|
6 |
+
* KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
7 |
+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
8 |
+
* PARTICULAR PURPOSE.
|
9 |
+
*/
|
10 |
+
class Hawksearch_Datafeed_Block_System_Config_Frontend_Feed_Clearts_Js
|
11 |
+
extends Mage_Adminhtml_Block_Template {
|
12 |
+
|
13 |
+
/**
|
14 |
+
* Sets javascript template to be included in the adminhtml js text_list block
|
15 |
+
*/
|
16 |
+
protected function _construct() {
|
17 |
+
parent::_construct();
|
18 |
+
$this->setTemplate('hawksearch/datafeed/clearts/js.phtml');
|
19 |
+
}
|
20 |
+
|
21 |
+
/**
|
22 |
+
* Returns the run all feeds async url
|
23 |
+
*
|
24 |
+
* @return string
|
25 |
+
*/
|
26 |
+
public function getClearUrl() {
|
27 |
+
$curStore = Mage::app()->getStore();
|
28 |
+
Mage::app()->setCurrentStore(1); //default storeID will always be 1
|
29 |
+
$myUrl = Mage::getUrl('hawksearch_datafeed/search/clearTimestamp');
|
30 |
+
Mage::app()->setCurrentStore($curStore);
|
31 |
+
return $myUrl;
|
32 |
+
}
|
33 |
+
}
|
app/code/community/Hawksearch/Datafeed/Block/System/Config/Frontend/Feed/Generate/Js.php
CHANGED
@@ -15,7 +15,7 @@ class Hawksearch_Datafeed_Block_System_Config_Frontend_Feed_Generate_Js extends
|
|
15 |
*/
|
16 |
protected function _construct() {
|
17 |
parent::_construct();
|
18 |
-
$this->setTemplate('hawksearch/
|
19 |
}
|
20 |
|
21 |
/**
|
@@ -24,10 +24,10 @@ class Hawksearch_Datafeed_Block_System_Config_Frontend_Feed_Generate_Js extends
|
|
24 |
* @return string
|
25 |
*/
|
26 |
public function getGenerateUrl() {
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
}
|
33 |
}
|
15 |
*/
|
16 |
protected function _construct() {
|
17 |
parent::_construct();
|
18 |
+
$this->setTemplate('hawksearch/datafeed/generate/js.phtml');
|
19 |
}
|
20 |
|
21 |
/**
|
24 |
* @return string
|
25 |
*/
|
26 |
public function getGenerateUrl() {
|
27 |
+
return Mage::getUrl('hawksearch_datafeed/search/runFeedGeneration/',
|
28 |
+
array(
|
29 |
+
'_secure' => true,
|
30 |
+
'_store' => Mage_Core_Model_App::ADMIN_STORE_ID
|
31 |
+
));
|
32 |
}
|
33 |
}
|
app/code/community/Hawksearch/Datafeed/Block/System/Config/Frontend/Feed/Generateimagecache/Js.php
CHANGED
@@ -15,7 +15,7 @@ class Hawksearch_Datafeed_Block_System_Config_Frontend_Feed_Generateimagecache_J
|
|
15 |
*/
|
16 |
protected function _construct() {
|
17 |
parent::_construct();
|
18 |
-
$this->setTemplate('hawksearch/
|
19 |
}
|
20 |
|
21 |
/**
|
@@ -24,10 +24,10 @@ class Hawksearch_Datafeed_Block_System_Config_Frontend_Feed_Generateimagecache_J
|
|
24 |
* @return string
|
25 |
*/
|
26 |
public function getGenerateUrl() {
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
}
|
33 |
}
|
15 |
*/
|
16 |
protected function _construct() {
|
17 |
parent::_construct();
|
18 |
+
$this->setTemplate('hawksearch/datafeed/generateimagecache/js.phtml');
|
19 |
}
|
20 |
|
21 |
/**
|
24 |
* @return string
|
25 |
*/
|
26 |
public function getGenerateUrl() {
|
27 |
+
return Mage::getUrl('hawksearch_datafeed/search/runImageCacheGeneration/',
|
28 |
+
array(
|
29 |
+
'_secure' => true,
|
30 |
+
'_store' => Mage_Core_Model_App::ADMIN_STORE_ID
|
31 |
+
));
|
32 |
}
|
33 |
}
|
app/code/community/Hawksearch/Datafeed/Block/System/Config/Frontend/Feed/Timestamp.php
ADDED
@@ -0,0 +1,51 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) 2013 Hawksearch (www.hawksearch.com) - All Rights Reserved
|
4 |
+
*
|
5 |
+
* THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
|
6 |
+
* KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
7 |
+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
8 |
+
* PARTICULAR PURPOSE.
|
9 |
+
*/
|
10 |
+
class Hawksearch_Datafeed_Block_System_Config_Frontend_Feed_Timestamp
|
11 |
+
extends Mage_Adminhtml_Block_System_Config_Form_Field {
|
12 |
+
|
13 |
+
protected $_buttonId = 'clear_timestamp_button';
|
14 |
+
|
15 |
+
protected function _prepareLayout() {
|
16 |
+
$block = $this->getLayout()->createBlock('hawksearch_datafeed/system_config_frontend_feed_clearts_js');
|
17 |
+
$block->setData('button_id', $this->_buttonId);
|
18 |
+
$this->getLayout()->getBlock('js')->append($block);
|
19 |
+
return parent::_prepareLayout();
|
20 |
+
|
21 |
+
}
|
22 |
+
protected function _getElementHtml(Varien_Data_Form_Element_Abstract $element) {
|
23 |
+
$timeinfo = $this->getTimeInfo();
|
24 |
+
$button = $this->getButton();
|
25 |
+
if($timeinfo == false) {
|
26 |
+
$timeinfo = '<p>Last generation time unknown, next generation will be a full export</p>';
|
27 |
+
$button->setData('class', 'disabled');
|
28 |
+
}
|
29 |
+
return $timeinfo . $button->toHtml();
|
30 |
+
}
|
31 |
+
|
32 |
+
private function getTimeInfo() {
|
33 |
+
$filename = Mage::helper('hawksearch_datafeed/data')->getFeedFilePath() . DS . "timestamp.txt";
|
34 |
+
if(!file_exists($filename)) {
|
35 |
+
return false;
|
36 |
+
}
|
37 |
+
$lines = file($filename);
|
38 |
+
$lastrun = new Zend_Date($lines[0]);
|
39 |
+
$lastrun->setTimezone(Mage::getStoreConfig('general/locale/timezone'));
|
40 |
+
return sprintf('<p id="hawksearch_lastgen_time">Last Generation at <strong>%s</strong> contained <strong>%d</strong> records</p>', $lastrun->toString("M/d/YYYY h:mm a"), $lines[1]);
|
41 |
+
}
|
42 |
+
private function getButton() {
|
43 |
+
$button = $this->getLayout()->createBlock('adminhtml/widget_button')
|
44 |
+
->setData(array(
|
45 |
+
'id' => $this->_buttonId,
|
46 |
+
'label' => $this->helper('hawksearch_datafeed')->__('Clear Timestamp'),
|
47 |
+
'onclick' => 'javascript:hawkSearchTimestamp.clear(); return false;'
|
48 |
+
));
|
49 |
+
return $button;
|
50 |
+
}
|
51 |
+
}
|
app/code/community/Hawksearch/Datafeed/Helper/Data.php
CHANGED
@@ -214,7 +214,7 @@ class Hawksearch_Datafeed_Helper_Data extends Mage_Core_Helper_Abstract {
|
|
214 |
return Mage::getStoreConfig(self::SECTION . self::FEED_GROUP . 'output_file_ext');
|
215 |
}
|
216 |
public function getFeedFilePath() {
|
217 |
-
return Mage::getStoreConfig(self::SECTION . self::FEED_GROUP . 'feed_path');
|
218 |
}
|
219 |
function mtime() {
|
220 |
list($usec, $sec) = explode(" ", microtime());
|
214 |
return Mage::getStoreConfig(self::SECTION . self::FEED_GROUP . 'output_file_ext');
|
215 |
}
|
216 |
public function getFeedFilePath() {
|
217 |
+
return Mage::getBaseDir('base') . DS . Mage::getStoreConfig(self::SECTION . self::FEED_GROUP . 'feed_path');
|
218 |
}
|
219 |
function mtime() {
|
220 |
list($usec, $sec) = explode(" ", microtime());
|
app/code/community/Hawksearch/Datafeed/Helper/Feed.php
CHANGED
@@ -11,95 +11,47 @@
|
|
11 |
class Hawksearch_Datafeed_Helper_Feed {
|
12 |
|
13 |
protected $_feedFilePath = null;
|
14 |
-
|
15 |
-
/**
|
16 |
-
* Open socket to feed generation url with store id as passed parameter.
|
17 |
-
*
|
18 |
-
* @param Mage_Core_Model_Store $store
|
19 |
-
* @param array $urlParts
|
20 |
-
* @throws Mage_Core_Exception
|
21 |
-
*/
|
22 |
-
#public function postToGenerateFeed($store, $urlParts) {
|
23 |
-
public function postToGenerateFeed($urlParts) {
|
24 |
-
$feedSocket = @fsockopen($urlParts['host'], 80, $errNo, $errStr, 10);
|
25 |
-
|
26 |
-
if (!$feedSocket) {
|
27 |
-
Mage::throwException("Err. #$errNo: Cannot access feed generation uri.");
|
28 |
-
}
|
29 |
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
$
|
36 |
-
$
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
if (!$result) {
|
51 |
-
Mage::throwException("Error writing to feed generation uri.");
|
52 |
-
}
|
53 |
-
|
54 |
-
fclose($feedSocket);
|
55 |
-
}
|
56 |
-
|
57 |
-
/**
|
58 |
-
* Returns url that controls feed generation
|
59 |
-
*
|
60 |
-
* @return string
|
61 |
-
*/
|
62 |
-
|
63 |
-
public function getGenerateFeedUrl() {
|
64 |
-
$curStore = Mage::app()->getStore();
|
65 |
-
Mage::app()->setCurrentStore(1); //default storeID will always be 1
|
66 |
-
$myUrl = Mage::getUrl('hawksearch_datafeed/search/generateFeed');
|
67 |
-
Mage::app()->setCurrentStore($curStore);
|
68 |
-
return $myUrl;
|
69 |
-
}
|
70 |
-
|
71 |
/**
|
72 |
* Asynchronously starts a feed generation for each store
|
73 |
*/
|
74 |
public function generateFeedsForAllStores() {
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
foreach($stores as $store) {
|
93 |
-
$this->postToGenerateFeed($store, $urlParts);
|
94 |
-
}
|
95 |
-
*/
|
96 |
-
}
|
97 |
-
catch (Exception $e) {
|
98 |
-
Mage::logException($e);
|
99 |
-
}
|
100 |
-
} else {
|
101 |
-
Mage::throwException("Error Generating Feed Locks. Generation temporarily locked.");
|
102 |
-
}
|
103 |
}
|
104 |
|
105 |
/**
|
@@ -109,7 +61,7 @@ class Hawksearch_Datafeed_Helper_Feed {
|
|
109 |
*/
|
110 |
public function getFeedFilePath() {
|
111 |
if ($this->_feedFilePath === null) {
|
112 |
-
|
113 |
}
|
114 |
return $this->_feedFilePath;
|
115 |
}
|
11 |
class Hawksearch_Datafeed_Helper_Feed {
|
12 |
|
13 |
protected $_feedFilePath = null;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
14 |
|
15 |
+
public function refreshImageCache($storeid) {
|
16 |
+
$tmppath = sys_get_temp_dir();
|
17 |
+
$tmpfile = tempnam($tmppath, 'hawkfeed_');
|
18 |
+
|
19 |
+
$parts = explode(DIRECTORY_SEPARATOR, __FILE__);
|
20 |
+
array_pop($parts);
|
21 |
+
$parts[] = 'runfeed.php';
|
22 |
+
$runfile = implode(DIRECTORY_SEPARATOR, $parts);
|
23 |
+
$root = getcwd();
|
24 |
+
|
25 |
+
$f = fopen($tmpfile, 'w');
|
26 |
+
fwrite($f, '#!/bin/sh' . "\n");
|
27 |
+
$phpbin = PHP_BINDIR . DIRECTORY_SEPARATOR . "php";
|
28 |
+
|
29 |
+
fwrite($f, "$phpbin $runfile -i $storeid -r $root -t $tmpfile\n");
|
30 |
+
|
31 |
+
shell_exec("/bin/sh $tmpfile > /dev/null 2>&1 &");
|
32 |
+
|
33 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
34 |
/**
|
35 |
* Asynchronously starts a feed generation for each store
|
36 |
*/
|
37 |
public function generateFeedsForAllStores() {
|
38 |
+
$tmppath = sys_get_temp_dir();
|
39 |
+
$tmpfile = tempnam($tmppath, 'hawkfeed_');
|
40 |
+
|
41 |
+
$parts = explode(DIRECTORY_SEPARATOR, __FILE__);
|
42 |
+
array_pop($parts);
|
43 |
+
$parts[] = 'runfeed.php';
|
44 |
+
$runfile = implode(DIRECTORY_SEPARATOR, $parts);
|
45 |
+
$root = getcwd();
|
46 |
+
|
47 |
+
$f = fopen($tmpfile, 'w');
|
48 |
+
fwrite($f, '#!/bin/sh' . "\n");
|
49 |
+
$phpbin = PHP_BINDIR . DIRECTORY_SEPARATOR . "php";
|
50 |
+
|
51 |
+
fwrite($f, "$phpbin $runfile -r $root -t $tmpfile\n");
|
52 |
+
|
53 |
+
shell_exec("/bin/sh $tmpfile > /dev/null 2>&1 &");
|
54 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
55 |
}
|
56 |
|
57 |
/**
|
61 |
*/
|
62 |
public function getFeedFilePath() {
|
63 |
if ($this->_feedFilePath === null) {
|
64 |
+
$this->_feedFilePath = $this->makeVarPath(array('hawksearch', 'feeds'));
|
65 |
}
|
66 |
return $this->_feedFilePath;
|
67 |
}
|
app/code/community/Hawksearch/Datafeed/Helper/runfeed.php
ADDED
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) 2013 Hawksearch (www.hawksearch.com) - All Rights Reserved
|
4 |
+
*
|
5 |
+
* THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
|
6 |
+
* KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
7 |
+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
8 |
+
* PARTICULAR PURPOSE.
|
9 |
+
*/
|
10 |
+
|
11 |
+
$opts = getopt('r:t:i:');
|
12 |
+
chdir($opts['r']);
|
13 |
+
require 'app/Mage.php';
|
14 |
+
|
15 |
+
Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID);
|
16 |
+
/** @var Mage $app */
|
17 |
+
$app = Mage::app();
|
18 |
+
|
19 |
+
$helper = Mage::helper('hawksearch_datafeed/feed');
|
20 |
+
$feed = Mage::getModel('hawksearch_datafeed/feed');
|
21 |
+
|
22 |
+
if ($helper->thereAreFeedLocks()) {
|
23 |
+
Mage::throwException("One or more feeds are being generated. Generation temporarily locked.");
|
24 |
+
}
|
25 |
+
if ($helper->CreateFeedLocks()) {
|
26 |
+
if (isset($opts['i'])) {
|
27 |
+
$feed->refreshImageCache($opts['i']);
|
28 |
+
} else {
|
29 |
+
$feed->generateFeed();
|
30 |
+
}
|
31 |
+
}
|
32 |
+
unlink($opts['t']);
|
33 |
+
|
app/code/community/Hawksearch/Datafeed/Model/Cron.php
CHANGED
@@ -18,16 +18,12 @@ class Hawksearch_Datafeed_Model_Cron {
|
|
18 |
if(!Mage::getStoreConfig('hawksearch_datafeed/cron/disabled'))
|
19 |
{
|
20 |
try {
|
21 |
-
|
22 |
$msg = "HawkSeach Feed Generated!";
|
23 |
}
|
24 |
catch (Exception $e) {
|
25 |
$msg = $e->getMessage();
|
26 |
}
|
27 |
-
catch (Exception $e) {
|
28 |
-
$msg = "Unknown Error: {$e->getMessage()} in {$e->getFile()} on line {$e->getLine()}. Please contact HawkSearch.";
|
29 |
-
}
|
30 |
-
|
31 |
$this->_sendEmail($msg);
|
32 |
}
|
33 |
}
|
18 |
if(!Mage::getStoreConfig('hawksearch_datafeed/cron/disabled'))
|
19 |
{
|
20 |
try {
|
21 |
+
Mage::getModel('hawksearch_datafeed/feed')->generateFeed();
|
22 |
$msg = "HawkSeach Feed Generated!";
|
23 |
}
|
24 |
catch (Exception $e) {
|
25 |
$msg = $e->getMessage();
|
26 |
}
|
|
|
|
|
|
|
|
|
27 |
$this->_sendEmail($msg);
|
28 |
}
|
29 |
}
|
app/code/community/Hawksearch/Datafeed/Model/Feed.php
CHANGED
@@ -1,7 +1,5 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
#error_reporting(E_ALL);
|
4 |
-
#ini_set('display_errors', '1');
|
5 |
/**
|
6 |
* Copyright (c) 2013 Hawksearch (www.hawksearch.com) - All Rights Reserved
|
7 |
*
|
@@ -23,6 +21,7 @@ class Hawksearch_Datafeed_Model_Feed extends Mage_Core_Model_Abstract {
|
|
23 |
$_totalProductCount,
|
24 |
$_imageHeight,
|
25 |
$_imageWidth,
|
|
|
26 |
$_optionType;
|
27 |
|
28 |
private $countryMap;
|
@@ -39,7 +38,7 @@ class Hawksearch_Datafeed_Model_Feed extends Mage_Core_Model_Abstract {
|
|
39 |
// Ignore user aborts and allow the script
|
40 |
// to run forever
|
41 |
ignore_user_abort(true); // If Varnish decides that the results timed out. Browsers are better behaved.
|
42 |
-
set_time_limit(0); // Even with DB calls not counting towards execution time, it's still a long running script.
|
43 |
/** @var $helper Hawksearch_Datafeed_Helper_Data */
|
44 |
$helper = Mage::helper('hawksearch_datafeed/data');
|
45 |
|
@@ -53,7 +52,7 @@ class Hawksearch_Datafeed_Model_Feed extends Mage_Core_Model_Abstract {
|
|
53 |
|
54 |
$this->_feedPath = $helper->getFeedFilePath();
|
55 |
if (empty($this->_feedPath)) {
|
56 |
-
$this->_feedPath = 'var/hawksearch/feeds';
|
57 |
}
|
58 |
|
59 |
$this->_batchSize = $helper->getBatchLimit();
|
@@ -71,10 +70,24 @@ class Hawksearch_Datafeed_Model_Feed extends Mage_Core_Model_Abstract {
|
|
71 |
$this->outputFileDelimiter = $helper->getOutputFileDelimiter();
|
72 |
$this->bufferSize = $helper->getBufferSize();
|
73 |
$this->outputFileExtension = $helper->getOutputFileExtension();
|
|
|
74 |
|
75 |
parent::__construct();
|
76 |
}
|
77 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
78 |
/**
|
79 |
* Retrieves the values of select/multiselect fields, to be dereferenced into values useful to Hawk
|
80 |
*
|
@@ -119,8 +132,6 @@ EOSQL;
|
|
119 |
|
120 |
// Prepare the array of attribute codes and compile a unique list of IDs to dereference
|
121 |
|
122 |
-
//die($sql.'Andrew');
|
123 |
-
|
124 |
if ($rows = $write->fetchAll($sql)) {
|
125 |
foreach ($rows as $row) {
|
126 |
$opts = explode(',', $row['value']);
|
@@ -208,13 +219,8 @@ EOSQL;
|
|
208 |
*
|
209 |
* @return boolean
|
210 |
*/
|
211 |
-
|
212 |
protected function _getAttributeData() {
|
213 |
-
|
214 |
-
//$path = $this->_feedPath;
|
215 |
-
$done = false;
|
216 |
-
$offset = 0;
|
217 |
-
|
218 |
$filename = $this->_feedPath . DS . "attributes" . '.' . $this->outputFileExtension;
|
219 |
$arrayExcludeFields = explode(",", $this->_excludedFields);
|
220 |
|
@@ -230,34 +236,30 @@ EOSQL;
|
|
230 |
'varchar',
|
231 |
'decimal',
|
232 |
'datetime',
|
233 |
-
// 'catalog_category_product',
|
234 |
);
|
235 |
|
236 |
-
$multiSelectValues = $this->getMultiSelectValues();
|
237 |
-
|
238 |
$write = $this->_getConnection();
|
239 |
|
240 |
-
// This _should_ be escaped to prevent SQL injection... however the source of data is in the
|
241 |
-
// admin panel so _should_ be generally safe. TODO: Check the Magento writer DB object for ways
|
242 |
-
// to escape content.
|
243 |
$excludeFields = implode("', '", $arrayExcludeFields);
|
244 |
if (!empty($excludeFields)) {
|
|
|
245 |
$excludeFields = " AND attribute_code NOT IN ('" . $excludeFields . "')";
|
246 |
}
|
247 |
|
|
|
248 |
$output = new CsvWriter($filename, $this->outputFileDelimiter, $this->bufferSize);
|
|
|
249 |
$output->appendRow(array('unique_id', 'key', 'value'));
|
|
|
250 |
|
251 |
-
//$content = "unique_id\tkey\tvalue\n";
|
252 |
-
|
253 |
-
// Loop through each of the catalog_product_entity_XXX tables separately. Despite tribal knowledge to the contrary
|
254 |
-
// among DB developers, in this specific case multiple queries happens to be faster than multiple joins.
|
255 |
foreach ($tables as $table) {
|
256 |
-
|
|
|
257 |
$done = false;
|
258 |
$offset = 0;
|
259 |
$valueTable = $productEntityValueTable . $table;
|
260 |
if ($table == "catalog_category_product") {
|
|
|
261 |
|
262 |
$selectQry = <<<EOSQL
|
263 |
SELECT
|
@@ -265,6 +267,7 @@ SELECT
|
|
265 |
e.sku,
|
266 |
a.attribute_code,
|
267 |
a.source_model,
|
|
|
268 |
a.attribute_id,
|
269 |
a.attribute_code As value
|
270 |
FROM
|
@@ -276,13 +279,7 @@ WHERE
|
|
276 |
ORDER BY e.entity_id ASC
|
277 |
EOSQL;
|
278 |
|
279 |
-
|
280 |
-
} elseif ($this->_optionType == 'eav') {
|
281 |
-
// No temporary table any more, after exhaustive testing. It takes just as long to itterate
|
282 |
-
// through the temp table as it does through a fresh query, plus the temp table has the
|
283 |
-
// overhead of being set up in the first place. This query takes less than 2 seconds each
|
284 |
-
// time it is called, compared to the over 5 minutes it took previously, when the temp
|
285 |
-
// table was a good idea.
|
286 |
$valColumn = "v.value";
|
287 |
$eaovTable = '';
|
288 |
if ($table == 'int') {
|
@@ -298,12 +295,13 @@ SELECT
|
|
298 |
e.sku,
|
299 |
a.attribute_code,
|
300 |
a.source_model,
|
|
|
301 |
a.attribute_id,
|
302 |
$valColumn
|
303 |
FROM
|
304 |
$productEntityTable e
|
305 |
LEFT JOIN
|
306 |
-
$valueTable v ON e.entity_id = v.entity_id
|
307 |
LEFT JOIN
|
308 |
$eavAttributeTable a ON v.attribute_id = a.attribute_id
|
309 |
$eaovTable
|
@@ -314,63 +312,18 @@ ORDER BY e.entity_id ASC
|
|
314 |
EOSQL;
|
315 |
Mage::log($selectQry);
|
316 |
|
317 |
-
} else {
|
318 |
-
$selectQry = <<<EOSQL
|
319 |
-
SELECT
|
320 |
-
e.entity_id,
|
321 |
-
e.sku,
|
322 |
-
a.attribute_code,
|
323 |
-
a.source_model,
|
324 |
-
a.attribute_id,
|
325 |
-
v.value
|
326 |
-
FROM
|
327 |
-
$productEntityTable e
|
328 |
-
FF0000LEFT JOIN
|
329 |
-
$valueTable v ON e.entity_id = v.entity_id
|
330 |
-
LEFT JOIN
|
331 |
-
$eavAttributeTable a ON v.attribute_id = a.attribute_id
|
332 |
-
WHERE
|
333 |
-
e.entity_type_id = $this->_entityTypeId
|
334 |
-
$excludeFields
|
335 |
-
ORDER BY e.entity_id ASC
|
336 |
-
EOSQL;
|
337 |
}
|
338 |
|
339 |
while (!$done) {
|
340 |
-
|
341 |
-
//die( "select Query: " . $selectQry);
|
342 |
-
|
343 |
try {
|
344 |
-
// Messy, messy, messy. I appologize in advance.
|
345 |
-
// Perhaps some prose will help.
|
346 |
-
// The fetchAll() within this first if() statement runs the query, including the LIMIT and OFFSET.
|
347 |
-
// Then, we itterate through the results. If the value is a number or a list of comma-separated numbers, then
|
348 |
-
// we attempt to dereference to the actual values for the field.
|
349 |
-
// Finally, at the end of itterating through the results, we write to disk and reset our loop-specific variables before
|
350 |
-
// launching back through the while() above and doing fetchAll() again.
|
351 |
-
// Also note the foreach (tables as table) above, which moves us to the next DB table.
|
352 |
if (($rows = $write->fetchAll($selectQry . ' LIMIT ' . $offset . ', ' . $this->_batchSize)) && (count($rows) > 0)) {
|
|
|
353 |
foreach ($rows as $row) {
|
354 |
-
|
355 |
-
|
356 |
-
if ($values[0] == "category_ids" && $row['attribute_code'] == 'category_ids') {
|
357 |
-
$category_ids_for_export = "";
|
358 |
-
$select_qry = 'SELECT category_id FROM ' . $categoryProductTable . ' WHERE product_id = "' . $row['entity_id'] . '"';
|
359 |
-
$rows1 = $write->fetchAll($select_qry);
|
360 |
-
foreach ($rows1 as $category_data) {
|
361 |
-
//$content .= "\"" . $row['sku'] . "\"\t\"category_id\"\t\"" . $category_data['category_id'] . "\"\n";
|
362 |
-
$output->appendRow(array($row['sku'], 'category_id', $category_data['category_id']));
|
363 |
-
}
|
364 |
-
} elseif ($row['attribute_code'] == 'country_of_manufacture') {
|
365 |
-
//$content .= "\"" . $row['sku'] . "\"\t\"" . $row['attribute_code'] . "\"\t\"" . str_replace("\"", "\"\"", $countryMap[$row['value']]) . "\"\n";
|
366 |
-
$output->appendRow(array($row['sku'], $row['attribute_code'], $this->getCountryName($row['value'])));
|
367 |
-
|
368 |
-
} else if (is_numeric($values[0])) {
|
369 |
foreach ($values as $val) {
|
370 |
-
if (
|
371 |
-
//$content .= "\"" . $row['sku'] . "\"\t\"" . $row['attribute_code'] . "\"\t\"" . str_replace("\"", "\"\"", $multiSelectValues[$row['attribute_code']][$val]) . "\"\n";
|
372 |
-
$output->appendRow(array($row['sku'], $row['attribute_code'], $multiSelectValues[$row['attribute_code']][$val]));
|
373 |
-
} elseif ($table == 'int' && !empty($row['source_model'])) {
|
374 |
$source = Mage::getSingleton($row['source_model']);
|
375 |
if ($row['source_model'] == 'eav/entity_attribute_source_table') {
|
376 |
$attribute = Mage::getModel('eav/entity_attribute')->load($row['attribute_id']);
|
@@ -378,65 +331,91 @@ EOSQL;
|
|
378 |
}
|
379 |
$output->appendRow(array($row['sku'], $row['attribute_code'], $source->getOptionText($row['value'])));
|
380 |
} else {
|
381 |
-
//$content .= "\"" . $row['sku'] . "\"\t\"" . $row['attribute_code'] . "\"\t\"" . str_replace("\"", "\"\"", $val) . "\"\n";
|
382 |
$output->appendRow(array($row['sku'], $row['attribute_code'], $val));
|
383 |
}
|
384 |
}
|
385 |
-
}
|
386 |
-
|
387 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
388 |
$output->appendRow(array($row['sku'], $row['attribute_code'], $row['value']));
|
389 |
}
|
390 |
}
|
391 |
-
|
392 |
-
|
393 |
-
//$this->writeFile($filename, '', $content, ($firstRecord ? 1 : 2));
|
394 |
-
|
395 |
-
// Reset for the next iteration.
|
396 |
-
// Commentary: It is necessary to set for next iteration at the end, rather than the beginning, because the first
|
397 |
-
// iteration has special cases, such as setting the TSV header and removing/re-creating the file itself.
|
398 |
-
// $firstRecord = false;
|
399 |
-
// $content = '';
|
400 |
$offset += $this->_batchSize;
|
401 |
} else {
|
|
|
402 |
$done = true;
|
403 |
}
|
404 |
} catch (Exception $e) {
|
405 |
// remove lock
|
406 |
Mage::helper('hawksearch_datafeed/feed')->RemoveFeedLocks();
|
407 |
|
408 |
-
|
409 |
-
|
410 |
-
}
|
411 |
return false;
|
412 |
}
|
413 |
}
|
414 |
}
|
415 |
-
|
416 |
/* custom attribute code/category_id */
|
417 |
$collection = Mage::getModel('catalog/product')->getCollection();
|
418 |
$collection->addAttributeToSelect('sku');
|
419 |
-
|
420 |
if (!Mage::helper('hawksearch_datafeed/data')->getAllowDisabledAttribute()) {
|
|
|
421 |
$collection->addAttributeToFilter('status', Mage_Catalog_Model_Product_Status::STATUS_ENABLED);
|
422 |
}
|
423 |
-
if(!Mage::helper('hawksearch_datafeed/data')->isIncludeOutOfStockItems()) {
|
|
|
424 |
/** @var Mage_CatalogInventory_Model_Stock $stockfilter */
|
425 |
$stockfilter = Mage::getSingleton('cataloginventory/stock');
|
426 |
$stockfilter->addInStockFilterToCollection($collection);
|
427 |
}
|
428 |
|
|
|
429 |
$collection->setPageSize($this->_batchSize);
|
430 |
$totalPages = $collection->getLastPageNumber();
|
|
|
431 |
|
432 |
$currentPage = 1;
|
433 |
do {
|
|
|
434 |
$collection->setCurPage($currentPage);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
435 |
/** @var Mage_Catalog_Model_Product $product */
|
436 |
foreach ($collection as $product) {
|
437 |
-
foreach($product->getCategoryIds() as $id) {
|
438 |
$output->appendRow(array($product->getSku(), 'category_id', $id));
|
439 |
}
|
|
|
|
|
|
|
|
|
440 |
/* Example of custom attribute generation */
|
441 |
// $product->load('media_gallery');
|
442 |
// /** @var Varien_Data_Collection $images */
|
@@ -455,90 +434,117 @@ EOSQL;
|
|
455 |
// }
|
456 |
// }
|
457 |
}
|
458 |
-
$collection->clear();
|
459 |
$currentPage++;
|
460 |
} while ($currentPage <= $totalPages);
|
461 |
|
|
|
462 |
return true;
|
463 |
}
|
464 |
|
|
|
|
|
|
|
|
|
465 |
protected function _getCategoryData() {
|
466 |
-
$
|
467 |
-
$offset = 0;
|
468 |
$filename = $this->_feedPath . DS . "hierarchy" . '.' . $this->outputFileExtension;
|
469 |
|
470 |
-
|
471 |
-
|
472 |
-
$
|
473 |
-
$
|
474 |
-
$categoryVarCharTable = $this->_tablePrefix . 'catalog_category_entity_varchar';
|
475 |
-
|
476 |
-
$write = $this->_getConnection();
|
477 |
|
478 |
-
$
|
479 |
-
|
480 |
-
|
481 |
-
a.parent_id,
|
482 |
-
b.value,
|
483 |
-
a.position
|
484 |
-
FROM
|
485 |
-
$categoryTable AS a
|
486 |
-
LEFT JOIN
|
487 |
-
$categoryVarCharTable AS b ON a.entity_id = b.entity_id
|
488 |
-
WHERE
|
489 |
-
b.attribute_id IN
|
490 |
-
(
|
491 |
-
SELECT
|
492 |
-
attribute_id
|
493 |
-
FROM
|
494 |
-
$eavAttributesTable
|
495 |
-
WHERE
|
496 |
-
attribute_code = 'name'
|
497 |
-
)
|
498 |
-
AND
|
499 |
-
b.store_id = '0'
|
500 |
-
AND
|
501 |
-
a.parent_id != '0'
|
502 |
-
ORDER BY
|
503 |
-
a.position ASC
|
504 |
-
EOSQL;
|
505 |
|
506 |
-
|
507 |
$output = new CsvWriter($filename, $this->outputFileDelimiter, $this->bufferSize);
|
508 |
-
$
|
509 |
-
$output->appendRow(array('
|
|
|
|
|
|
|
510 |
|
511 |
-
|
512 |
-
|
513 |
-
|
514 |
-
|
515 |
-
|
516 |
-
|
517 |
-
|
518 |
-
|
519 |
-
|
520 |
-
|
521 |
-
|
522 |
-
//$content = '';
|
523 |
-
}
|
524 |
-
} else {
|
525 |
-
$done = true;
|
526 |
}
|
527 |
-
|
528 |
-
|
529 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
530 |
|
531 |
-
|
532 |
-
|
533 |
-
|
534 |
-
|
|
|
535 |
}
|
536 |
-
}
|
537 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
538 |
return true;
|
539 |
}
|
540 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
541 |
protected function _getProductData() {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
542 |
$done = false;
|
543 |
$offset = 0;
|
544 |
$filename = $this->_feedPath . DS . "items" . '.' . $this->outputFileExtension;
|
@@ -586,33 +592,35 @@ WHERE attribute_code IN
|
|
586 |
'msrp',
|
587 |
'special_price',
|
588 |
'status',
|
|
|
589 |
'$brandAttribute'
|
590 |
)
|
591 |
AND entity_type_id = '$entity_type_id'
|
592 |
EOSQL;
|
593 |
|
|
|
594 |
if ($codeRows = $write->fetchAll($attrCodesQuery)) {
|
595 |
foreach ($codeRows as $row) {
|
596 |
$attrCodes[$row['attribute_code']] = $row['attribute_id'];
|
597 |
}
|
598 |
}
|
|
|
599 |
|
600 |
$disabled_sql = '';
|
601 |
$CONN = ' WHERE ';
|
602 |
if (!$allowDisabled) {
|
603 |
-
$disabled_sql = "LEFT JOIN $productEntityIntTable AS T6 ON P.entity_id = T6.entity_id AND T6.attribute_id = '" . $attrCodes['status'] . "'";
|
604 |
}
|
605 |
|
606 |
-
$brandAttribute = Mage::helper('hawksearch_datafeed/data')->getBrandAttribute();
|
607 |
if (!empty($brandAttribute)) {
|
608 |
$brand_select = ", B5.value AS Brand";
|
609 |
-
$brand_sql = "LEFT JOIN " . $productEntityIntTable . " AS B5 ON P.entity_id = B5.entity_id AND B5.attribute_id = '" . $attrCodes[$brandAttribute] . "'";
|
610 |
}
|
611 |
-
$urlfield = ", CONCAT(V1.value, '.
|
612 |
-
$urljoin = "LEFT JOIN $productEntityUrlTable AS V1 ON P.entity_id = V1.entity_id AND V1.attribute_id = '" . $attrCodes['url_key'] . "'";
|
613 |
if (!Mage::getSingleton('core/resource')->getConnection('core_write')->isTableExists('catalog_product_entity_url_key')) {
|
614 |
-
$
|
615 |
-
$urljoin = '';
|
616 |
}
|
617 |
|
618 |
$select_qry = "SELECT P.attribute_set_id, P.entity_id AS ProductID, P.type_id, P.sku, P.has_options, V.value AS Name, T1.value AS ProdDesc, T2.value AS ShortDesc, T3.value AS MetaKeyword, T5.value AS visibility, D.value AS Price, S.value AS Special_Price, SDF.value As Special_Date_From, SDT.value As Special_Date_To, ST.qty, ST.is_in_stock AS IsInStock, X.value AS Msrp" . $brand_select . ", R.parent_id AS GroupID $urlfield,
|
@@ -622,36 +630,40 @@ EOSQL;
|
|
622 |
ELSE CONCAT('', V2.value)
|
623 |
END AS Image
|
624 |
FROM $productEntityTable AS P
|
625 |
-
INNER JOIN " . $productEntityVarCharTable . " AS V ON P.entity_id = V.entity_id AND V.attribute_id = '" . $attrCodes['name'] . "'
|
626 |
-
INNER JOIN " . $catalogInventoryStockTable . " AS ST ON P.entity_id = ST.product_id
|
|
|
627 |
" . $urljoin . "
|
628 |
-
LEFT JOIN " . $productEntityVarCharTable . " AS V2 ON P.entity_id = V2.entity_id AND V2.attribute_id = '" . $attrCodes['image'] . "'
|
629 |
-
LEFT JOIN " . $productEntityTextTable . " AS T1 ON P.entity_id = T1.entity_id AND T1.attribute_id = '" . $attrCodes['description'] . "'
|
630 |
-
LEFT JOIN " . $productEntityTextTable . " AS T2 ON P.entity_id = T2.entity_id AND T2.attribute_id = '" . $attrCodes['short_description'] . "'
|
631 |
-
LEFT JOIN " . $productEntityTextTable . " AS T3 ON P.entity_id = T3.entity_id AND T3.attribute_id = '" . $attrCodes['meta_keyword'] . "'
|
632 |
-
LEFT JOIN " . $productEntityIntTable . " AS T5 ON P.entity_id = T5.entity_id AND T5.attribute_id = '" . $attrCodes['visibility'] . "'
|
633 |
" . $disabled_sql . "
|
634 |
-
LEFT JOIN " . $productEntityDecimalTable . " AS D ON P.entity_id = D.entity_id AND D.attribute_id = '" . $attrCodes['price'] . "'
|
635 |
-
LEFT JOIN " . $productEntityDateTimeTable . " AS SDF ON P.entity_id = SDF.entity_id AND SDF.attribute_id = '" . $attrCodes['special_from_date'] . "'
|
636 |
-
LEFT JOIN " . $productEntityDateTimeTable . " AS SDT ON P.entity_id = SDT.entity_id AND SDT.attribute_id = '" . $attrCodes['special_to_date'] . "'
|
637 |
" . $brand_sql . "
|
638 |
-
LEFT JOIN " . $productEntityDecimalTable . " AS X ON P.entity_id = X.entity_id AND X.attribute_id = '" . $attrCodes['msrp'] . "'
|
639 |
-
|
640 |
LEFT JOIN " . $productRelationTable . " AS R ON P.entity_id = R.parent_id OR P.entity_id = R.child_id
|
641 |
-
LEFT JOIN " . $productEntityDecimalTable . " AS S ON P.entity_id = S.entity_id AND S.attribute_id = '" . $attrCodes['special_price'] . "'";
|
642 |
|
643 |
if (!Mage::helper('hawksearch_datafeed/data')->isIncludeOutOfStockItems()) {
|
|
|
644 |
$select_qry .= " $CONN ST.is_in_stock = 1";
|
645 |
$CONN = ' AND ';
|
646 |
}
|
647 |
if (!$allowDisabled) {
|
|
|
648 |
$select_qry .= " $CONN T6.value = 1 ";
|
649 |
$CONN = ' AND ';
|
650 |
}
|
651 |
|
652 |
-
|
653 |
-
|
|
|
654 |
$output = new CsvWriter($filename, $this->outputFileDelimiter, $this->bufferSize);
|
|
|
655 |
$output->appendRow(array(
|
656 |
'product_id',
|
657 |
'unique_id',
|
@@ -676,9 +688,13 @@ EOSQL;
|
|
676 |
'keyword',
|
677 |
'metric_inventory'));
|
678 |
|
|
|
679 |
while (!$done) {
|
680 |
try {
|
681 |
-
|
|
|
|
|
|
|
682 |
if (count($rows) > 0) {
|
683 |
foreach ($rows as $row) {
|
684 |
//$name = empty($row['Name']) ? $row['Name'] : str_replace("\"", "\"\"", $row['Name']);
|
@@ -694,7 +710,6 @@ EOSQL;
|
|
694 |
} else {
|
695 |
$brand_text = "";
|
696 |
}
|
697 |
-
//$content .= "\"" . $row['ProductID'] . "\"\t\"" . $row['sku'] . "\"\t\"" . $name . "\"\t\"" . $row['Link'] . "\"\t\"" . $row['Image'] . "\"\t\"" . $row['Msrp'] . "\"\t\"" . $row['Price'] . "\"\t\"" . $row['Special_Price'] . "\"\t\"" . $row['Special_Date_From'] . "\"\t\"" . $row['Special_Date_To'] . "\"\t\"" . $row['GroupID'] . "\"\t\"" . $shortdescription . "\"\t\"" . $description . "\"\t\"" . $brand_text . "\"\t\"" . $row['sku'] . "\"\t\"0\"\t\"0\"\t\"0\"\t\"0\"\t\"" . $data_is_on_sale . "\"\t\"" . $metakeyword . "\"\t\"" . $row['qty'] . "\"\n";
|
698 |
$output->appendRow(array(
|
699 |
$row['ProductID'],
|
700 |
$row['sku'],
|
@@ -721,30 +736,27 @@ EOSQL;
|
|
721 |
|
722 |
}
|
723 |
$offset += $this->_batchSize;
|
724 |
-
//$this->writeFile($filename, '', $content, ($firstRecord ? 1 : 2));
|
725 |
-
//$firstRecord = false;
|
726 |
-
//$content = '';
|
727 |
}
|
728 |
} else {
|
|
|
729 |
$done = true;
|
730 |
}
|
731 |
} catch (Exception $e) {
|
732 |
// remove lock
|
733 |
Mage::helper('hawksearch_datafeed/feed')->RemoveFeedLocks();
|
734 |
|
735 |
-
|
736 |
-
|
737 |
-
|
738 |
-
|
739 |
return false;
|
740 |
}
|
741 |
} // end while
|
|
|
742 |
return true;
|
743 |
}
|
744 |
|
745 |
protected function _getContentData() {
|
746 |
-
|
747 |
-
|
748 |
$done = false;
|
749 |
$offset = 0;
|
750 |
$baseurl = Mage::getUrl();
|
@@ -759,13 +771,18 @@ EOSQL;
|
|
759 |
|
760 |
$write = $this->_getConnection();
|
761 |
|
762 |
-
|
763 |
$output = new CsvWriter($filename, $this->outputFileDelimiter, $this->bufferSize);
|
|
|
764 |
$output->appendRow(array('unique_id', 'name', 'url_detail', 'description_short', 'created_date'));
|
|
|
765 |
|
|
|
766 |
while (!$done) {
|
767 |
try {
|
768 |
-
|
|
|
|
|
769 |
if (($numRows = count($rows)) && $numRows > 0) {
|
770 |
foreach ($rows as $row) {
|
771 |
//$content .= $row['page_id'] . "\t" . $row['title'] . "\t" . $row['Link'] . "\t" . $row['content_heading'] . "\t" . $row['creation_time'] . "\n";
|
@@ -773,9 +790,6 @@ EOSQL;
|
|
773 |
}
|
774 |
|
775 |
$offset += $this->_batchSize;
|
776 |
-
// $this->writeFile($filename, '', $content, ($firstRecord ? 1 : 2));
|
777 |
-
// $firstRecord = false;
|
778 |
-
// $content = '';
|
779 |
} else {
|
780 |
$done = true;
|
781 |
}
|
@@ -786,50 +800,16 @@ EOSQL;
|
|
786 |
// remove lock
|
787 |
Mage::helper('hawksearch_datafeed/feed')->RemoveFeedLocks();
|
788 |
|
789 |
-
|
790 |
-
|
791 |
-
|
792 |
return false;
|
793 |
}
|
794 |
} // end while
|
|
|
795 |
return true;
|
796 |
}
|
797 |
|
798 |
-
/*private function writeFile($filename, $header, $content, $recordcount) {
|
799 |
-
if ($recordcount === 1) {
|
800 |
-
if (file_exists($filename)) {
|
801 |
-
unlink($filename);
|
802 |
-
}
|
803 |
-
}
|
804 |
-
|
805 |
-
if (!file_exists($filename)) {
|
806 |
-
$handle = fopen($filename, "a");
|
807 |
-
fclose($handle);
|
808 |
-
}
|
809 |
-
|
810 |
-
if (is_writable($filename)) {
|
811 |
-
if (!$handle = fopen($filename, 'a')) {
|
812 |
-
if ($this->isLoggingEnabled) {
|
813 |
-
Mage::log("Cannot open file (" . $filename . ")", null, 'hawksearch_errors.log');
|
814 |
-
}
|
815 |
-
return false;
|
816 |
-
}
|
817 |
-
if (fwrite($handle, $content) === FALSE) {
|
818 |
-
if ($this->isLoggingEnabled) {
|
819 |
-
Mage::log("Cannot write to file (" . $filename . ")", null, 'hawksearch_errors.log');
|
820 |
-
}
|
821 |
-
return false;
|
822 |
-
}
|
823 |
-
return true; // Success, wrote ($somecontent) to file ($filename);
|
824 |
-
fclose($handle);
|
825 |
-
} else {
|
826 |
-
if ($this->isLoggingEnabled) {
|
827 |
-
Mage::log("The file " . $filename . " is not writable", null, 'hawksearch_errors.log');
|
828 |
-
}
|
829 |
-
}
|
830 |
-
return true;
|
831 |
-
}*/
|
832 |
-
|
833 |
public function getCountryName($code) {
|
834 |
/* map friendly country_of_origin names */
|
835 |
if (!isset($this->countryMap)) {
|
@@ -845,10 +825,18 @@ EOSQL;
|
|
845 |
return isset($this->countryMap[$code]) ? $this->countryMap[$code] : $code;
|
846 |
}
|
847 |
|
848 |
-
public function generateFeed(
|
849 |
try {
|
850 |
-
|
851 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
852 |
|
853 |
//exports Category Data
|
854 |
$this->_getCategoryData();
|
@@ -856,49 +844,74 @@ EOSQL;
|
|
856 |
//exports Product Data
|
857 |
$this->_getProductData();
|
858 |
|
|
|
|
|
|
|
859 |
//exports CMS / Content Data
|
860 |
$this->_getContentData();
|
861 |
|
862 |
-
//refresh image cache
|
863 |
-
|
864 |
-
|
865 |
// remove locks
|
866 |
Mage::helper('hawksearch_datafeed/feed')->RemoveFeedLocks();
|
|
|
867 |
} catch (Exception $e) {
|
868 |
// remove lock
|
869 |
Mage::helper('hawksearch_datafeed/feed')->RemoveFeedLocks();
|
870 |
-
|
871 |
-
if ($this->isLoggingEnabled) {
|
872 |
-
Mage::log(sprintf('Exception: %s', $e->getMessage()), null, 'hawksearch_errors.log');
|
873 |
-
}
|
874 |
}
|
|
|
875 |
}
|
876 |
|
877 |
-
public function refreshImageCache() {
|
878 |
-
$
|
879 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
880 |
|
|
|
|
|
|
|
881 |
$pages = $products->getLastPageNumber();
|
|
|
882 |
$currentPage = 1;
|
883 |
|
884 |
do {
|
|
|
|
|
885 |
$products->setCurPage($currentPage);
|
886 |
$products->load();
|
887 |
|
888 |
foreach ($products as $product) {
|
889 |
if (empty($this->_imageHeight)) {
|
890 |
-
|
|
|
|
|
|
|
891 |
} else {
|
892 |
-
|
|
|
|
|
|
|
893 |
}
|
894 |
}
|
895 |
|
896 |
$currentPage++;
|
897 |
|
898 |
//clear collection and free memory
|
899 |
-
$products->clear();
|
900 |
|
901 |
} while ($currentPage <= $pages);
|
|
|
|
|
|
|
902 |
}
|
903 |
|
904 |
/**
|
@@ -989,12 +1002,14 @@ class CsvWriter {
|
|
989 |
}
|
990 |
|
991 |
public function closeOutput() {
|
992 |
-
if (
|
|
|
|
|
|
|
993 |
if (false === fclose($this->outputFile)) {
|
994 |
-
throw new Exception("CsvWriter: Failed to close
|
995 |
}
|
996 |
$this->outputOpen = false;
|
997 |
}
|
998 |
}
|
999 |
-
|
1000 |
}
|
1 |
<?php
|
2 |
|
|
|
|
|
3 |
/**
|
4 |
* Copyright (c) 2013 Hawksearch (www.hawksearch.com) - All Rights Reserved
|
5 |
*
|
21 |
$_totalProductCount,
|
22 |
$_imageHeight,
|
23 |
$_imageWidth,
|
24 |
+
$_storeId,
|
25 |
$_optionType;
|
26 |
|
27 |
private $countryMap;
|
38 |
// Ignore user aborts and allow the script
|
39 |
// to run forever
|
40 |
ignore_user_abort(true); // If Varnish decides that the results timed out. Browsers are better behaved.
|
41 |
+
set_time_limit(0); // Even with DB calls not counting towards execution time, it's still a long running script.
|
42 |
/** @var $helper Hawksearch_Datafeed_Helper_Data */
|
43 |
$helper = Mage::helper('hawksearch_datafeed/data');
|
44 |
|
52 |
|
53 |
$this->_feedPath = $helper->getFeedFilePath();
|
54 |
if (empty($this->_feedPath)) {
|
55 |
+
$this->_feedPath = Mage::getBaseDir('base') . DS . 'var/hawksearch/feeds';
|
56 |
}
|
57 |
|
58 |
$this->_batchSize = $helper->getBatchLimit();
|
70 |
$this->outputFileDelimiter = $helper->getOutputFileDelimiter();
|
71 |
$this->bufferSize = $helper->getBufferSize();
|
72 |
$this->outputFileExtension = $helper->getOutputFileExtension();
|
73 |
+
$this->_storeId = 0;
|
74 |
|
75 |
parent::__construct();
|
76 |
}
|
77 |
|
78 |
+
/**
|
79 |
+
* Adds a log entry to the hawksearch proxy log. Logging must
|
80 |
+
* be enabled for both the module and Magneto
|
81 |
+
* (See System >> Configuration >> Developer >> Log Settings
|
82 |
+
*
|
83 |
+
* @param $message
|
84 |
+
*/
|
85 |
+
public function log($message) {
|
86 |
+
if ($this->isLoggingEnabled) {
|
87 |
+
Mage::log("HAWKSEARCH: $message", null, 'hawksearch.log');
|
88 |
+
}
|
89 |
+
}
|
90 |
+
|
91 |
/**
|
92 |
* Retrieves the values of select/multiselect fields, to be dereferenced into values useful to Hawk
|
93 |
*
|
132 |
|
133 |
// Prepare the array of attribute codes and compile a unique list of IDs to dereference
|
134 |
|
|
|
|
|
135 |
if ($rows = $write->fetchAll($sql)) {
|
136 |
foreach ($rows as $row) {
|
137 |
$opts = explode(',', $row['value']);
|
219 |
*
|
220 |
* @return boolean
|
221 |
*/
|
|
|
222 |
protected function _getAttributeData() {
|
223 |
+
$this->log('starting _getAttributeData');
|
|
|
|
|
|
|
|
|
224 |
$filename = $this->_feedPath . DS . "attributes" . '.' . $this->outputFileExtension;
|
225 |
$arrayExcludeFields = explode(",", $this->_excludedFields);
|
226 |
|
236 |
'varchar',
|
237 |
'decimal',
|
238 |
'datetime',
|
|
|
239 |
);
|
240 |
|
|
|
|
|
241 |
$write = $this->_getConnection();
|
242 |
|
|
|
|
|
|
|
243 |
$excludeFields = implode("', '", $arrayExcludeFields);
|
244 |
if (!empty($excludeFields)) {
|
245 |
+
$this->log('adding exclude fields');
|
246 |
$excludeFields = " AND attribute_code NOT IN ('" . $excludeFields . "')";
|
247 |
}
|
248 |
|
249 |
+
$this->log(sprintf('going to open feed file %s', $filename));
|
250 |
$output = new CsvWriter($filename, $this->outputFileDelimiter, $this->bufferSize);
|
251 |
+
$this->log('feed file open, appending header');
|
252 |
$output->appendRow(array('unique_id', 'key', 'value'));
|
253 |
+
$this->log('header appended');
|
254 |
|
|
|
|
|
|
|
|
|
255 |
foreach ($tables as $table) {
|
256 |
+
$this->log(sprintf('starting to pull from attribute table %s', $table));
|
257 |
+
|
258 |
$done = false;
|
259 |
$offset = 0;
|
260 |
$valueTable = $productEntityValueTable . $table;
|
261 |
if ($table == "catalog_category_product") {
|
262 |
+
$this->log('creating query for catalog_category_product');
|
263 |
|
264 |
$selectQry = <<<EOSQL
|
265 |
SELECT
|
267 |
e.sku,
|
268 |
a.attribute_code,
|
269 |
a.source_model,
|
270 |
+
a.frontend_input,
|
271 |
a.attribute_id,
|
272 |
a.attribute_code As value
|
273 |
FROM
|
279 |
ORDER BY e.entity_id ASC
|
280 |
EOSQL;
|
281 |
|
282 |
+
} else {
|
|
|
|
|
|
|
|
|
|
|
|
|
283 |
$valColumn = "v.value";
|
284 |
$eaovTable = '';
|
285 |
if ($table == 'int') {
|
295 |
e.sku,
|
296 |
a.attribute_code,
|
297 |
a.source_model,
|
298 |
+
a.frontend_input,
|
299 |
a.attribute_id,
|
300 |
$valColumn
|
301 |
FROM
|
302 |
$productEntityTable e
|
303 |
LEFT JOIN
|
304 |
+
$valueTable v ON e.entity_id = v.entity_id and v.store_id = 0
|
305 |
LEFT JOIN
|
306 |
$eavAttributeTable a ON v.attribute_id = a.attribute_id
|
307 |
$eaovTable
|
312 |
EOSQL;
|
313 |
Mage::log($selectQry);
|
314 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
315 |
}
|
316 |
|
317 |
while (!$done) {
|
318 |
+
$this->log(sprintf('querying data for table %s at offset %d', $table, $offset));
|
|
|
|
|
319 |
try {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
320 |
if (($rows = $write->fetchAll($selectQry . ' LIMIT ' . $offset . ', ' . $this->_batchSize)) && (count($rows) > 0)) {
|
321 |
+
$this->log(sprintf('fetch all succeeded for att type %s, processing %d rows', $table, count($rows)));
|
322 |
foreach ($rows as $row) {
|
323 |
+
if ($row['frontend_input'] == 'multiselect') {
|
324 |
+
$values = explode(',', $row['value']);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
325 |
foreach ($values as $val) {
|
326 |
+
if ($table == 'int' && !empty($row['source_model'])) {
|
|
|
|
|
|
|
327 |
$source = Mage::getSingleton($row['source_model']);
|
328 |
if ($row['source_model'] == 'eav/entity_attribute_source_table') {
|
329 |
$attribute = Mage::getModel('eav/entity_attribute')->load($row['attribute_id']);
|
331 |
}
|
332 |
$output->appendRow(array($row['sku'], $row['attribute_code'], $source->getOptionText($row['value'])));
|
333 |
} else {
|
|
|
334 |
$output->appendRow(array($row['sku'], $row['attribute_code'], $val));
|
335 |
}
|
336 |
}
|
337 |
+
} else if ($row['attribute_code'] == 'category_ids' && $row['value'] == "category_ids") {
|
338 |
+
$select_qry = 'SELECT category_id FROM ' . $categoryProductTable . ' WHERE product_id = "' . $row['entity_id'] . '"';
|
339 |
+
$rows1 = $write->fetchAll($select_qry);
|
340 |
+
foreach ($rows1 as $category_data) {
|
341 |
+
$output->appendRow(array($row['sku'], 'category_id', $category_data['category_id']));
|
342 |
+
}
|
343 |
+
} elseif ($row['attribute_code'] == 'country_of_manufacture') {
|
344 |
+
$output->appendRow(array($row['sku'], $row['attribute_code'], $this->getCountryName($row['value'])));
|
345 |
+
|
346 |
+
} elseif ($table == 'int' && !empty($row['source_model']) && $row['source_model'] != 'eav/entity_attribute_source_table') {
|
347 |
+
try {
|
348 |
+
$source = Mage::getSingleton($row['source_model']);
|
349 |
+
$attribute = Mage::getModel('eav/entity_attribute')->load($row['attribute_id']);
|
350 |
+
$source->setAttribute($attribute);
|
351 |
+
$output->appendRow(array($row['sku'], $row['attribute_code'], $source->getOptionText($row['value'])));
|
352 |
+
} catch (Exception $e) {
|
353 |
+
$this->log(sprintf('%s - Caught Exception on line %d or %s: %s', date('c'), $e->getLine(), $e->getFile(), $e->getTraceAsString()));
|
354 |
+
$output->appendRow(array($row['sku'], $row['attribute_code'], $row['value']));
|
355 |
+
}
|
356 |
+
} else {
|
357 |
$output->appendRow(array($row['sku'], $row['attribute_code'], $row['value']));
|
358 |
}
|
359 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
360 |
$offset += $this->_batchSize;
|
361 |
} else {
|
362 |
+
$this->log(sprintf('done with table %s', $table));
|
363 |
$done = true;
|
364 |
}
|
365 |
} catch (Exception $e) {
|
366 |
// remove lock
|
367 |
Mage::helper('hawksearch_datafeed/feed')->RemoveFeedLocks();
|
368 |
|
369 |
+
$this->log(sprintf('%s - Exception thrown on line %d or %s: %s', date('c'), $e->getLine(), $e->getFile(), $e->getTraceAsString()));
|
370 |
+
$this->log('exiting function _getAttributeData() due to exception');
|
|
|
371 |
return false;
|
372 |
}
|
373 |
}
|
374 |
}
|
375 |
+
$this->log('going to get product collection for category id selection');
|
376 |
/* custom attribute code/category_id */
|
377 |
$collection = Mage::getModel('catalog/product')->getCollection();
|
378 |
$collection->addAttributeToSelect('sku');
|
379 |
+
//$collection->addAttributeToFilter('visibility', array('neq' => Mage_Catalog_Model_Product_Visibility::VISIBILITY_NOT_VISIBLE));
|
380 |
if (!Mage::helper('hawksearch_datafeed/data')->getAllowDisabledAttribute()) {
|
381 |
+
$this->log('adding status filter');
|
382 |
$collection->addAttributeToFilter('status', Mage_Catalog_Model_Product_Status::STATUS_ENABLED);
|
383 |
}
|
384 |
+
if (!Mage::helper('hawksearch_datafeed/data')->isIncludeOutOfStockItems()) {
|
385 |
+
$this->log('adding out of stock filter');
|
386 |
/** @var Mage_CatalogInventory_Model_Stock $stockfilter */
|
387 |
$stockfilter = Mage::getSingleton('cataloginventory/stock');
|
388 |
$stockfilter->addInStockFilterToCollection($collection);
|
389 |
}
|
390 |
|
391 |
+
$this->log(sprintf('setting page size to %d', $this->_batchSize));
|
392 |
$collection->setPageSize($this->_batchSize);
|
393 |
$totalPages = $collection->getLastPageNumber();
|
394 |
+
$this->log(sprintf('retrieved %d total pages', $totalPages));
|
395 |
|
396 |
$currentPage = 1;
|
397 |
do {
|
398 |
+
$this->log(sprintf('setting current page to %d', $currentPage));
|
399 |
$collection->setCurPage($currentPage);
|
400 |
+
$collection->clear();
|
401 |
+
$this->log(sprintf('going to process %d products on page %d', $collection->count(), $currentPage));
|
402 |
+
|
403 |
+
/*
|
404 |
+
* add ratings information
|
405 |
+
*/
|
406 |
+
/** @var Mage_Review_Model_Review $review */
|
407 |
+
$review = Mage::getSingleton('review/review');
|
408 |
+
$review->appendSummary($collection);
|
409 |
+
|
410 |
/** @var Mage_Catalog_Model_Product $product */
|
411 |
foreach ($collection as $product) {
|
412 |
+
foreach ($product->getCategoryIds() as $id) {
|
413 |
$output->appendRow(array($product->getSku(), 'category_id', $id));
|
414 |
}
|
415 |
+
if(($rs = $product->getRatingSummary()) && $rs->getReviewsCount() > 0){
|
416 |
+
$output->appendRow(array($product->getSku(), 'rating_summary', $rs->getRatingSummary()));
|
417 |
+
$output->appendRow(array($product->getSku(), 'reviews_count', $rs->getReviewsCount()));
|
418 |
+
}
|
419 |
/* Example of custom attribute generation */
|
420 |
// $product->load('media_gallery');
|
421 |
// /** @var Varien_Data_Collection $images */
|
434 |
// }
|
435 |
// }
|
436 |
}
|
|
|
437 |
$currentPage++;
|
438 |
} while ($currentPage <= $totalPages);
|
439 |
|
440 |
+
$this->log('done processing attributes');
|
441 |
return true;
|
442 |
}
|
443 |
|
444 |
+
/**
|
445 |
+
* @return bool
|
446 |
+
* @throws Mage_Core_Exception
|
447 |
+
*/
|
448 |
protected function _getCategoryData() {
|
449 |
+
$this->log('starting _getCategoryData()');
|
|
|
450 |
$filename = $this->_feedPath . DS . "hierarchy" . '.' . $this->outputFileExtension;
|
451 |
|
452 |
+
$collection = Mage::getModel('catalog/category')->getCollection();
|
453 |
+
$collection->addAttributeToSelect(array('name', 'is_active', 'parent_id', 'position'));
|
454 |
+
$collection->addAttributeToFilter('is_active', array('eq' => '1'));
|
455 |
+
$collection->addAttributeToSort('entity_id')->addAttributeToSort('parent_id')->addAttributeToSort('position');
|
|
|
|
|
|
|
456 |
|
457 |
+
$collection->setPageSize($this->_batchSize);
|
458 |
+
$pages = $collection->getLastPageNumber();
|
459 |
+
$currentPage = 1;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
460 |
|
461 |
+
$this->log(sprintf('going to open feed file %s', $filename));
|
462 |
$output = new CsvWriter($filename, $this->outputFileDelimiter, $this->bufferSize);
|
463 |
+
$this->log('file open, going to append header and root');
|
464 |
+
$output->appendRow(array('category_id', 'category_name', 'parent_category_id', 'sort_order', 'is_active', 'category_url'));
|
465 |
+
$output->appendRow(array('1', 'Root', '0', '0', '1', '/'));
|
466 |
+
$this->log('header and root appended');
|
467 |
+
$base = Mage::app()->getStore()->getBaseUrl();
|
468 |
|
469 |
+
$cats = array();
|
470 |
+
do {
|
471 |
+
$this->log(sprintf('getting category page %d', $currentPage));
|
472 |
+
$collection->setCurPage($currentPage);
|
473 |
+
$collection->clear();
|
474 |
+
$collection->load();
|
475 |
+
foreach ($collection as $cat) {
|
476 |
+
$fullUrl = Mage::helper('catalog/category')->getCategoryUrl($cat);
|
477 |
+
$category_url = substr($fullUrl, strlen($base));
|
478 |
+
if(substr($category_url, 0, 1) != '/'){
|
479 |
+
$category_url = '/' . $category_url;
|
|
|
|
|
|
|
|
|
480 |
}
|
481 |
+
$this->log(sprintf("got full category url: %s, returning relative url %s", $fullUrl, $category_url));
|
482 |
+
$cats[] = array(
|
483 |
+
'id' => $cat->getId(),
|
484 |
+
'name' => $cat->getName(),
|
485 |
+
'pid' => $cat->getParentId(),
|
486 |
+
'pos' => $cat->getPosition(),
|
487 |
+
'ia' => $cat->getIsActive(),
|
488 |
+
'url' => $category_url
|
489 |
+
);
|
490 |
+
}
|
491 |
+
$currentPage++;
|
492 |
+
} while ($currentPage <= $pages);
|
493 |
|
494 |
+
$rcid = Mage::app()->getStore()->getRootCategoryId();
|
495 |
+
$myCategories = array();
|
496 |
+
foreach($cats as $storecat){
|
497 |
+
if($storecat['id'] == $rcid){
|
498 |
+
$myCategories[] = $storecat;
|
499 |
}
|
500 |
+
}
|
501 |
|
502 |
+
$this->r_find($rcid, $cats, $myCategories);
|
503 |
+
|
504 |
+
foreach($myCategories as $final) {
|
505 |
+
$output->appendRow(array(
|
506 |
+
$final['id'],
|
507 |
+
$final['name'],
|
508 |
+
$final['pid'],
|
509 |
+
$final['pos'],
|
510 |
+
$final['ia'],
|
511 |
+
$final['url']
|
512 |
+
));
|
513 |
+
}
|
514 |
+
|
515 |
+
$this->log('done with _getCategoryData()');
|
516 |
return true;
|
517 |
}
|
518 |
|
519 |
+
/**
|
520 |
+
* Recursively sets up the category tree without introducing
|
521 |
+
* duplicate data.
|
522 |
+
*
|
523 |
+
* @param $pid
|
524 |
+
* @param $all
|
525 |
+
* @param $tree
|
526 |
+
*/
|
527 |
+
private function r_find($pid, &$all, &$tree) {
|
528 |
+
foreach($all as $item) {
|
529 |
+
if($item['pid'] == $pid) {
|
530 |
+
$tree[] = $item;
|
531 |
+
$this->r_find($item['id'], $all, $tree);
|
532 |
+
}
|
533 |
+
}
|
534 |
+
}
|
535 |
+
|
536 |
protected function _getProductData() {
|
537 |
+
$this->log('starting _getProductData()');
|
538 |
+
/** @var Mage_Catalog_Helper_Product $helper */
|
539 |
+
$helper = Mage::helper('catalog/product');
|
540 |
+
$urlSuffix = $helper->getProductUrlSuffix(0);
|
541 |
+
if (!empty($urlSuffix)) {
|
542 |
+
if (substr($urlSuffix, 0, 1) != '.') {
|
543 |
+
$urlSuffix = '.' . $urlSuffix;
|
544 |
+
}
|
545 |
+
}
|
546 |
+
$this->log(sprintf("using '%s' for the product url suffix", $urlSuffix));
|
547 |
+
|
548 |
$done = false;
|
549 |
$offset = 0;
|
550 |
$filename = $this->_feedPath . DS . "items" . '.' . $this->outputFileExtension;
|
592 |
'msrp',
|
593 |
'special_price',
|
594 |
'status',
|
595 |
+
'url_key',
|
596 |
'$brandAttribute'
|
597 |
)
|
598 |
AND entity_type_id = '$entity_type_id'
|
599 |
EOSQL;
|
600 |
|
601 |
+
$this->log('fetching attribute codes');
|
602 |
if ($codeRows = $write->fetchAll($attrCodesQuery)) {
|
603 |
foreach ($codeRows as $row) {
|
604 |
$attrCodes[$row['attribute_code']] = $row['attribute_id'];
|
605 |
}
|
606 |
}
|
607 |
+
$this->log(sprintf('found %d codes: %s', count($attrCodes), implode("', '", array_keys($attrCodes))));
|
608 |
|
609 |
$disabled_sql = '';
|
610 |
$CONN = ' WHERE ';
|
611 |
if (!$allowDisabled) {
|
612 |
+
$disabled_sql = "LEFT JOIN $productEntityIntTable AS T6 ON P.entity_id = T6.entity_id AND T6.attribute_id = '" . $attrCodes['status'] . "' AND T6.store_id = '" . $this->_storeId . "'";
|
613 |
}
|
614 |
|
|
|
615 |
if (!empty($brandAttribute)) {
|
616 |
$brand_select = ", B5.value AS Brand";
|
617 |
+
$brand_sql = "LEFT JOIN " . $productEntityIntTable . " AS B5 ON P.entity_id = B5.entity_id AND B5.attribute_id = '" . $attrCodes[$brandAttribute] . "' AND B5.store_id = '" . $this->_storeId . "'";
|
618 |
}
|
619 |
+
$urlfield = ", CONCAT(V1.value, '" . $urlSuffix . "') AS Link";
|
620 |
+
$urljoin = "LEFT JOIN $productEntityUrlTable AS V1 ON P.entity_id = V1.entity_id AND V1.attribute_id = '" . $attrCodes['url_key'] . "' AND V1.store_id = '" . $this->_storeId . "'";
|
621 |
if (!Mage::getSingleton('core/resource')->getConnection('core_write')->isTableExists('catalog_product_entity_url_key')) {
|
622 |
+
$this->log('using catalog_product_entity_url_table');
|
623 |
+
$urljoin = ' LEFT JOIN ' . $productEntityVarCharTable . " AS V1 ON P.entity_id = V1.entity_id AND V1.attribute_id = '" . $attrCodes['url_key'] . "' AND V1.store_id = '" . $this->_storeId . "'";
|
624 |
}
|
625 |
|
626 |
$select_qry = "SELECT P.attribute_set_id, P.entity_id AS ProductID, P.type_id, P.sku, P.has_options, V.value AS Name, T1.value AS ProdDesc, T2.value AS ShortDesc, T3.value AS MetaKeyword, T5.value AS visibility, D.value AS Price, S.value AS Special_Price, SDF.value As Special_Date_From, SDT.value As Special_Date_To, ST.qty, ST.is_in_stock AS IsInStock, X.value AS Msrp" . $brand_select . ", R.parent_id AS GroupID $urlfield,
|
630 |
ELSE CONCAT('', V2.value)
|
631 |
END AS Image
|
632 |
FROM $productEntityTable AS P
|
633 |
+
INNER JOIN " . $productEntityVarCharTable . " AS V ON P.entity_id = V.entity_id AND V.attribute_id = '" . $attrCodes['name'] . "' AND V.store_id = '" . $this->_storeId . "'
|
634 |
+
INNER JOIN " . $catalogInventoryStockTable . " AS ST ON P.entity_id = ST.product_id
|
635 |
+
INNER JOIN " . $productEntityIntTable . " AS VIS ON VIS.entity_id = P.entity_id AND VIS.value != 1
|
636 |
" . $urljoin . "
|
637 |
+
LEFT JOIN " . $productEntityVarCharTable . " AS V2 ON P.entity_id = V2.entity_id AND V2.attribute_id = '" . $attrCodes['image'] . "' AND V2.store_id = '" . $this->_storeId . "'
|
638 |
+
LEFT JOIN " . $productEntityTextTable . " AS T1 ON P.entity_id = T1.entity_id AND T1.attribute_id = '" . $attrCodes['description'] . "' AND T1.store_id = '" . $this->_storeId . "'
|
639 |
+
LEFT JOIN " . $productEntityTextTable . " AS T2 ON P.entity_id = T2.entity_id AND T2.attribute_id = '" . $attrCodes['short_description'] . "' AND T2.store_id = '" . $this->_storeId . "'
|
640 |
+
LEFT JOIN " . $productEntityTextTable . " AS T3 ON P.entity_id = T3.entity_id AND T3.attribute_id = '" . $attrCodes['meta_keyword'] . "' AND T3 .store_id = '" . $this->_storeId . "'
|
641 |
+
LEFT JOIN " . $productEntityIntTable . " AS T5 ON P.entity_id = T5.entity_id AND T5.attribute_id = '" . $attrCodes['visibility'] . "' AND T5.store_id = '" . $this->_storeId . "'
|
642 |
" . $disabled_sql . "
|
643 |
+
LEFT JOIN " . $productEntityDecimalTable . " AS D ON P.entity_id = D.entity_id AND D.attribute_id = '" . $attrCodes['price'] . "' AND D.store_id = '" . $this->_storeId . "'
|
644 |
+
LEFT JOIN " . $productEntityDateTimeTable . " AS SDF ON P.entity_id = SDF.entity_id AND SDF.attribute_id = '" . $attrCodes['special_from_date'] . "' AND SDF.store_id = '" . $this->_storeId . "'
|
645 |
+
LEFT JOIN " . $productEntityDateTimeTable . " AS SDT ON P.entity_id = SDT.entity_id AND SDT.attribute_id = '" . $attrCodes['special_to_date'] . "' AND SDT.store_id = '" . $this->_storeId . "'
|
646 |
" . $brand_sql . "
|
647 |
+
LEFT JOIN " . $productEntityDecimalTable . " AS X ON P.entity_id = X.entity_id AND X.attribute_id = '" . $attrCodes['msrp'] . "' AND X.store_id = '" . $this->_storeId . "'
|
|
|
648 |
LEFT JOIN " . $productRelationTable . " AS R ON P.entity_id = R.parent_id OR P.entity_id = R.child_id
|
649 |
+
LEFT JOIN " . $productEntityDecimalTable . " AS S ON P.entity_id = S.entity_id AND S.attribute_id = '" . $attrCodes['special_price'] . "' AND S.store_id = '" . $this->_storeId . "'";
|
650 |
|
651 |
if (!Mage::helper('hawksearch_datafeed/data')->isIncludeOutOfStockItems()) {
|
652 |
+
$this->log('filtering for in-stock items');
|
653 |
$select_qry .= " $CONN ST.is_in_stock = 1";
|
654 |
$CONN = ' AND ';
|
655 |
}
|
656 |
if (!$allowDisabled) {
|
657 |
+
$this->log('filtering disabled items');
|
658 |
$select_qry .= " $CONN T6.value = 1 ";
|
659 |
$CONN = ' AND ';
|
660 |
}
|
661 |
|
662 |
+
$select_qry .= " GROUP BY P.entity_id ";
|
663 |
+
|
664 |
+
$this->log(sprintf('going to open feed file %s', $filename));
|
665 |
$output = new CsvWriter($filename, $this->outputFileDelimiter, $this->bufferSize);
|
666 |
+
$this->log('appending feed header');
|
667 |
$output->appendRow(array(
|
668 |
'product_id',
|
669 |
'unique_id',
|
688 |
'keyword',
|
689 |
'metric_inventory'));
|
690 |
|
691 |
+
$full_query = 'not yet set';
|
692 |
while (!$done) {
|
693 |
try {
|
694 |
+
$full_query = $select_qry . ' LIMIT ' . $offset . ', ' . $this->_batchSize;
|
695 |
+
$this->log(sprintf('going to fetch %d products starting at offset %d', $this->_batchSize, $offset));
|
696 |
+
if ($rows = $write->fetchAll($full_query)) {
|
697 |
+
$this->log(sprintf('query returned %d rows', count($rows)));
|
698 |
if (count($rows) > 0) {
|
699 |
foreach ($rows as $row) {
|
700 |
//$name = empty($row['Name']) ? $row['Name'] : str_replace("\"", "\"\"", $row['Name']);
|
710 |
} else {
|
711 |
$brand_text = "";
|
712 |
}
|
|
|
713 |
$output->appendRow(array(
|
714 |
$row['ProductID'],
|
715 |
$row['sku'],
|
736 |
|
737 |
}
|
738 |
$offset += $this->_batchSize;
|
|
|
|
|
|
|
739 |
}
|
740 |
} else {
|
741 |
+
$this->log('done fetching products');
|
742 |
$done = true;
|
743 |
}
|
744 |
} catch (Exception $e) {
|
745 |
// remove lock
|
746 |
Mage::helper('hawksearch_datafeed/feed')->RemoveFeedLocks();
|
747 |
|
748 |
+
$this->log(sprintf('%s - Exception thrown on line %d or %s: %s', date('c'), $e->getLine(), $e->getFile(), $e->getTraceAsString()));
|
749 |
+
$this->log(sprintf("\nSQL was:\n%s", $full_query));
|
750 |
+
$this->log('exiting function _getProductData() due to exception');
|
|
|
751 |
return false;
|
752 |
}
|
753 |
} // end while
|
754 |
+
$this->log('done with _getProductData()');
|
755 |
return true;
|
756 |
}
|
757 |
|
758 |
protected function _getContentData() {
|
759 |
+
$this->log('starting _getContentData()');
|
|
|
760 |
$done = false;
|
761 |
$offset = 0;
|
762 |
$baseurl = Mage::getUrl();
|
771 |
|
772 |
$write = $this->_getConnection();
|
773 |
|
774 |
+
$this->log(sprintf('going to open feed file %s', $filename));
|
775 |
$output = new CsvWriter($filename, $this->outputFileDelimiter, $this->bufferSize);
|
776 |
+
$this->log('feed file open, going to append header');
|
777 |
$output->appendRow(array('unique_id', 'name', 'url_detail', 'description_short', 'created_date'));
|
778 |
+
$this->log('header appended, going to fetch data');
|
779 |
|
780 |
+
$full_query = 'not yet set';
|
781 |
while (!$done) {
|
782 |
try {
|
783 |
+
$this->log(sprintf('going to fetch %d rows at offset %d', $this->_batchSize, $offset));
|
784 |
+
$full_query = $select_qry . ' LIMIT ' . $offset . ', ' . $this->_batchSize;
|
785 |
+
if ($rows = $write->fetchAll($full_query)) {
|
786 |
if (($numRows = count($rows)) && $numRows > 0) {
|
787 |
foreach ($rows as $row) {
|
788 |
//$content .= $row['page_id'] . "\t" . $row['title'] . "\t" . $row['Link'] . "\t" . $row['content_heading'] . "\t" . $row['creation_time'] . "\n";
|
790 |
}
|
791 |
|
792 |
$offset += $this->_batchSize;
|
|
|
|
|
|
|
793 |
} else {
|
794 |
$done = true;
|
795 |
}
|
800 |
// remove lock
|
801 |
Mage::helper('hawksearch_datafeed/feed')->RemoveFeedLocks();
|
802 |
|
803 |
+
$this->log(sprintf('%s - Exception thrown on line %d or %s: %s', date('c'), $e->getLine(), $e->getFile(), $e->getTraceAsString()));
|
804 |
+
$this->log(sprintf("\nSQL was:\n%s", $full_query));
|
805 |
+
$this->log('exiting function _getContentData() due to exception');
|
806 |
return false;
|
807 |
}
|
808 |
} // end while
|
809 |
+
$this->log('done fetching content data');
|
810 |
return true;
|
811 |
}
|
812 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
813 |
public function getCountryName($code) {
|
814 |
/* map friendly country_of_origin names */
|
815 |
if (!isset($this->countryMap)) {
|
825 |
return isset($this->countryMap[$code]) ? $this->countryMap[$code] : $code;
|
826 |
}
|
827 |
|
828 |
+
public function generateFeed() {
|
829 |
try {
|
830 |
+
$sid = Mage::app()->getWebsite()->getDefaultGroup()->getDefaultStoreId();
|
831 |
+
$h = Mage::helper("hawksearch_proxy");
|
832 |
+
if (!empty($h)) {
|
833 |
+
$sid = $h->getCategoryStoreId();
|
834 |
+
}
|
835 |
+
|
836 |
+
$this->log('starting environment for store id: ' . $sid);
|
837 |
+
/** @var Mage_Core_Model_App_Emulation $appEmulation */
|
838 |
+
$appEmulation = Mage::getSingleton('core/app_emulation');
|
839 |
+
$initialEnvironmentInfo = $appEmulation->startEnvironmentEmulation($sid);
|
840 |
|
841 |
//exports Category Data
|
842 |
$this->_getCategoryData();
|
844 |
//exports Product Data
|
845 |
$this->_getProductData();
|
846 |
|
847 |
+
//exports Attribute Data
|
848 |
+
$this->_getAttributeData();
|
849 |
+
|
850 |
//exports CMS / Content Data
|
851 |
$this->_getContentData();
|
852 |
|
853 |
+
//refresh image cache no longer part of feed generation
|
854 |
+
//$this->refreshImageCache();
|
855 |
+
$this->log('done generating data feed files, going to remove lock files.');
|
856 |
// remove locks
|
857 |
Mage::helper('hawksearch_datafeed/feed')->RemoveFeedLocks();
|
858 |
+
$appEmulation->stopEnvironmentEmulation($initialEnvironmentInfo);
|
859 |
} catch (Exception $e) {
|
860 |
// remove lock
|
861 |
Mage::helper('hawksearch_datafeed/feed')->RemoveFeedLocks();
|
862 |
+
$this->log(sprintf("General Exception %s at generateFeed() line %d, stack:\n%s", $e->getMessage(), $e->getLine(), $e->getTraceAsString()));
|
|
|
|
|
|
|
863 |
}
|
864 |
+
$this->log('done with generateFeed()');
|
865 |
}
|
866 |
|
867 |
+
public function refreshImageCache($storeid = null) {
|
868 |
+
$this->log('starting refreshImageCache()');
|
869 |
+
$sid = Mage::app()->getWebsite()->getDefaultGroup()->getDefaultStoreId();
|
870 |
+
$h = Mage::helper("hawksearch_proxy");
|
871 |
+
if (!empty($h)) {
|
872 |
+
$sid = $h->getCategoryStoreId();
|
873 |
+
}
|
874 |
+
|
875 |
+
$this->log('starting environment for store id: ' . $sid);
|
876 |
+
|
877 |
+
$appEmulation = Mage::getSingleton('core/app_emulation');
|
878 |
+
$initialEnvironmentInfo = $appEmulation->startEnvironmentEmulation($sid);
|
879 |
|
880 |
+
$products = Mage::getModel('catalog/product')
|
881 |
+
->getCollection()->addAttributeToSelect(array('image', 'small_image'));
|
882 |
+
$products->setPageSize(100);
|
883 |
$pages = $products->getLastPageNumber();
|
884 |
+
|
885 |
$currentPage = 1;
|
886 |
|
887 |
do {
|
888 |
+
$this->log(sprintf('going to page %d of images', $currentPage));
|
889 |
+
$products->clear();
|
890 |
$products->setCurPage($currentPage);
|
891 |
$products->load();
|
892 |
|
893 |
foreach ($products as $product) {
|
894 |
if (empty($this->_imageHeight)) {
|
895 |
+
$this->log(
|
896 |
+
sprintf('going to resize image for url: %s',
|
897 |
+
Mage::helper('catalog/image')->init($product, 'small_image')->resize($this->_imageWidth
|
898 |
+
)));
|
899 |
} else {
|
900 |
+
$this->log(
|
901 |
+
sprintf('going to resize image for url: %s',
|
902 |
+
Mage::helper('catalog/image')->init($product, 'small_image')->resize($this->_imageWidth, $this->_imageHeight
|
903 |
+
)));
|
904 |
}
|
905 |
}
|
906 |
|
907 |
$currentPage++;
|
908 |
|
909 |
//clear collection and free memory
|
|
|
910 |
|
911 |
} while ($currentPage <= $pages);
|
912 |
+
$this->log('done generating image cache, going to remove locks.');
|
913 |
+
Mage::helper('hawksearch_datafeed/feed')->RemoveFeedLocks();
|
914 |
+
$appEmulation->stopEnvironmentEmulation($initialEnvironmentInfo);
|
915 |
}
|
916 |
|
917 |
/**
|
1002 |
}
|
1003 |
|
1004 |
public function closeOutput() {
|
1005 |
+
if ($this->outputOpen) {
|
1006 |
+
if (false === fflush($this->outputFile)) {
|
1007 |
+
throw new Exception(sprintf("CsvWriter: Failed to flush feed file: %s", $this->finalDestinationPath));
|
1008 |
+
}
|
1009 |
if (false === fclose($this->outputFile)) {
|
1010 |
+
throw new Exception(sprintf("CsvWriter: Failed to close feed file ", $this->finalDestinationPath));
|
1011 |
}
|
1012 |
$this->outputOpen = false;
|
1013 |
}
|
1014 |
}
|
|
|
1015 |
}
|
app/code/community/Hawksearch/Datafeed/controllers/SearchController.php
CHANGED
@@ -15,58 +15,27 @@ class Hawksearch_Datafeed_SearchController extends Mage_Core_Controller_Front_Ac
|
|
15 |
$this->renderLayout();
|
16 |
}
|
17 |
|
18 |
-
public function indexAction () {
|
19 |
-
$coupon_code = $this->getRequest()->getParam('coupon_code'); //to automatically apply a coupon code
|
20 |
-
if ($coupon_code != '')
|
21 |
-
{
|
22 |
-
Mage::getSingleton("checkout/session")->setData("coupon_code",$coupon_code);
|
23 |
-
Mage::getSingleton('checkout/cart')->getQuote()->setCouponCode($coupon_code)->save();
|
24 |
-
Mage::getSingleton('core/session')->addSuccess($this->__('Coupon was automatically applied'));
|
25 |
-
}
|
26 |
-
$product_id = $this->getRequest()->getParam('product');
|
27 |
-
$qty = $this->getRequest()->getParam('qty'); //used if your qty is not hard coded
|
28 |
-
$cart = Mage::getModel('checkout/cart');
|
29 |
-
$cart->init();
|
30 |
-
if ($product_id == '') {
|
31 |
-
$this->_redirect('/');
|
32 |
-
}
|
33 |
-
$productModel = Mage::getModel('catalog/product')->load($product_id);
|
34 |
-
if (TRUE) {
|
35 |
-
try
|
36 |
-
{
|
37 |
-
$cart->addProduct($productModel, array('qty' => '1')); //qty is hard coded
|
38 |
-
}
|
39 |
-
catch (Exception $e) {
|
40 |
-
$this->_redirect('/');
|
41 |
-
}
|
42 |
-
}
|
43 |
-
$cart->save();
|
44 |
-
if ($this->getRequest()->isXmlHttpRequest()) {
|
45 |
-
exit('1');
|
46 |
-
}
|
47 |
-
$this->_redirect('checkout/cart');
|
48 |
-
}
|
49 |
/**
|
50 |
* API Call for Image CacheKey to get images from cache on auto resize.
|
51 |
*/
|
52 |
public function getCacheKeyAction() {
|
53 |
$response = array("error" => false);
|
54 |
try {
|
55 |
-
$
|
56 |
-
$
|
57 |
-
$
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
$
|
62 |
-
$
|
63 |
-
$
|
64 |
-
$imageArray = explode("/", $
|
65 |
-
|
66 |
-
|
67 |
-
$
|
68 |
-
|
69 |
-
|
70 |
}
|
71 |
|
72 |
$response['cache_key'] = $cache_key;
|
@@ -75,39 +44,11 @@ class Hawksearch_Datafeed_SearchController extends Mage_Core_Controller_Front_Ac
|
|
75 |
catch (Exception $e) {
|
76 |
$response['error'] = $e->getMessage();
|
77 |
}
|
78 |
-
catch (Exception $e) {
|
79 |
-
Mage::logException($e);
|
80 |
-
$response['error'] = "An unknown error occurred.";
|
81 |
-
}
|
82 |
$this->getResponse()
|
83 |
->setHeader("Content-Type", "application/json")
|
84 |
->setBody(json_encode($response));
|
85 |
}
|
86 |
|
87 |
-
/*public function getFormKeyAction() {
|
88 |
-
|
89 |
-
$response = array("error" => false);
|
90 |
-
try {
|
91 |
-
|
92 |
-
$formKey = Mage::getSingleton('core/session')->getFormKey();
|
93 |
-
$formGuid = Mage::helper('core/url')->getEncodedUrl();
|
94 |
-
$response['form_guid'] = $formGuid;
|
95 |
-
$response['form_key'] = $formKey;
|
96 |
-
$response['date_time'] = date('Y-m-d H:i:s');
|
97 |
-
}
|
98 |
-
catch (Exception $e) {
|
99 |
-
$response['error'] = $e->getMessage();
|
100 |
-
}
|
101 |
-
catch (Exception $e) {
|
102 |
-
Mage::logException($e);
|
103 |
-
$response['error'] = "An unknown error occurred.";
|
104 |
-
}
|
105 |
-
$this->getResponse()
|
106 |
-
->setHeader("Content-Type", "application/json")
|
107 |
-
->setBody(json_encode($response));
|
108 |
-
|
109 |
-
}*/
|
110 |
-
|
111 |
/**
|
112 |
* Asynchronous posting to feed generation url for each store.
|
113 |
*/
|
@@ -115,7 +56,15 @@ class Hawksearch_Datafeed_SearchController extends Mage_Core_Controller_Front_Ac
|
|
115 |
$response = array("error" => false);
|
116 |
|
117 |
try {
|
118 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
119 |
}
|
120 |
catch (Exception $e) {
|
121 |
Mage::logException($e);
|
@@ -137,8 +86,15 @@ class Hawksearch_Datafeed_SearchController extends Mage_Core_Controller_Front_Ac
|
|
137 |
if (!$storeId) {
|
138 |
$storeId = Mage::app()->getDefaultStoreView()->getId();
|
139 |
}
|
|
|
|
|
|
|
140 |
|
141 |
-
|
|
|
|
|
|
|
|
|
142 |
}
|
143 |
catch (Exception $e) {
|
144 |
Mage::logException($e);
|
@@ -148,24 +104,4 @@ class Hawksearch_Datafeed_SearchController extends Mage_Core_Controller_Front_Ac
|
|
148 |
->setHeader("Content-Type", "application/json")
|
149 |
->setBody(json_encode($response));
|
150 |
}
|
151 |
-
|
152 |
-
/**
|
153 |
-
* Generates a feed based on passed in store id. Defaults store id to default store
|
154 |
-
*/
|
155 |
-
public function generateFeedAction() {
|
156 |
-
$response = "";
|
157 |
-
try {
|
158 |
-
$storeId = $this->getRequest()->getParam("storeId");
|
159 |
-
|
160 |
-
if (!$storeId) {
|
161 |
-
$storeId = Mage::app()->getDefaultStoreView()->getId();
|
162 |
-
}
|
163 |
-
Mage::getModel('hawksearch_datafeed/feed')->setData('store_id', $storeId)->generateFeed(true);
|
164 |
-
}
|
165 |
-
catch (Exception $e) {
|
166 |
-
Mage::logException($e);
|
167 |
-
$response = "An unknown error occurred.";
|
168 |
-
}
|
169 |
-
$this->getResponse()->setBody($response);
|
170 |
-
}
|
171 |
}
|
15 |
$this->renderLayout();
|
16 |
}
|
17 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
18 |
/**
|
19 |
* API Call for Image CacheKey to get images from cache on auto resize.
|
20 |
*/
|
21 |
public function getCacheKeyAction() {
|
22 |
$response = array("error" => false);
|
23 |
try {
|
24 |
+
/** @var Mage_Catalog_Model_Resource_Product_Collection $coll */
|
25 |
+
$coll = Mage::getModel('catalog/product')->getCollection();
|
26 |
+
$coll->addAttributeToSelect('small_image');
|
27 |
+
$coll->addAttributeToFilter('small_image', array(
|
28 |
+
'notnull' => true
|
29 |
+
));
|
30 |
+
$coll->getSelect()->limit(100);
|
31 |
+
$item = $coll->getLastItem();
|
32 |
+
$path = (string) Mage::helper('catalog/image')->init($item, 'small_image');
|
33 |
+
$imageArray = explode("/", $path);
|
34 |
+
$cache_key = "";
|
35 |
+
foreach($imageArray as $part) {
|
36 |
+
if(preg_match('/[0-9a-fA-F]{32}/', $part)) {
|
37 |
+
$cache_key = $part;
|
38 |
+
}
|
39 |
}
|
40 |
|
41 |
$response['cache_key'] = $cache_key;
|
44 |
catch (Exception $e) {
|
45 |
$response['error'] = $e->getMessage();
|
46 |
}
|
|
|
|
|
|
|
|
|
47 |
$this->getResponse()
|
48 |
->setHeader("Content-Type", "application/json")
|
49 |
->setBody(json_encode($response));
|
50 |
}
|
51 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
52 |
/**
|
53 |
* Asynchronous posting to feed generation url for each store.
|
54 |
*/
|
56 |
$response = array("error" => false);
|
57 |
|
58 |
try {
|
59 |
+
$disabledFuncs = explode(',', ini_get('disable_functions'));
|
60 |
+
$isShellDisabled = is_array($disabledFuncs) ? in_array('shell_exec', $disabledFuncs) : true;
|
61 |
+
$isShellDisabled = (stripos(PHP_OS, 'win') === false) ? $isShellDisabled : true;
|
62 |
+
|
63 |
+
if($isShellDisabled) {
|
64 |
+
$response['error'] = 'This installation cannot run one off feed generations. Must use cron.';
|
65 |
+
} else {
|
66 |
+
Mage::helper('hawksearch_datafeed/feed')->generateFeedsForAllStores();
|
67 |
+
}
|
68 |
}
|
69 |
catch (Exception $e) {
|
70 |
Mage::logException($e);
|
86 |
if (!$storeId) {
|
87 |
$storeId = Mage::app()->getDefaultStoreView()->getId();
|
88 |
}
|
89 |
+
$disabledFuncs = explode(',', ini_get('disable_functions'));
|
90 |
+
$isShellDisabled = is_array($disabledFuncs) ? in_array('shell_exec', $disabledFuncs) : true;
|
91 |
+
$isShellDisabled = (stripos(PHP_OS, 'win') === false) ? $isShellDisabled : true;
|
92 |
|
93 |
+
if($isShellDisabled) {
|
94 |
+
$response['error'] = 'This installation cannot run one-off cache generations. Must use cron.';
|
95 |
+
} else {
|
96 |
+
Mage::helper('hawksearch_datafeed/feed')->refreshImageCache($storeId);
|
97 |
+
}
|
98 |
}
|
99 |
catch (Exception $e) {
|
100 |
Mage::logException($e);
|
104 |
->setHeader("Content-Type", "application/json")
|
105 |
->setBody(json_encode($response));
|
106 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
107 |
}
|
app/code/community/Hawksearch/Datafeed/etc/config.xml
CHANGED
@@ -12,7 +12,7 @@
|
|
12 |
<config>
|
13 |
<modules>
|
14 |
<Hawksearch_Datafeed>
|
15 |
-
<version>1.0.0
|
16 |
</Hawksearch_Datafeed>
|
17 |
</modules>
|
18 |
<global>
|
@@ -20,13 +20,6 @@
|
|
20 |
<hawksearch_datafeed>
|
21 |
<class>Hawksearch_Datafeed_Block</class>
|
22 |
</hawksearch_datafeed>
|
23 |
-
<!--
|
24 |
-
<adminhtml>
|
25 |
-
<rewrite>
|
26 |
-
<system_config_form>Hawksearch_Datafeed_Block_System_Config_Form</system_config_form>
|
27 |
-
</rewrite>
|
28 |
-
</adminhtml>
|
29 |
-
-->
|
30 |
</blocks>
|
31 |
<helpers>
|
32 |
<hawksearch_datafeed>
|
@@ -64,22 +57,17 @@
|
|
64 |
<logging_enabled>1</logging_enabled>
|
65 |
</general>
|
66 |
<feed>
|
67 |
-
<generate/>
|
68 |
-
<submittal/>
|
69 |
<batch_limit>10000</batch_limit>
|
70 |
<image_width>135</image_width>
|
71 |
-
<brand_attribute/>
|
72 |
<exclude_fields>description,short_description,options_container,gift_message_available,visibility,status,tax_class_id,required_options,msrp_display_actual_price_type,enable_googlecheckout,created_at,updated_at,sku</exclude_fields>
|
73 |
-
<stockstatus>
|
74 |
<itemstatus>0</itemstatus>
|
75 |
-
<option_type>eav</option_type>
|
76 |
<delimiter>tab</delimiter>
|
77 |
<buffer_size>65536</buffer_size>
|
78 |
<output_file_ext>txt</output_file_ext>
|
79 |
<feed_path>var/hawksearch/feeds</feed_path>
|
80 |
</feed>
|
81 |
<cron>
|
82 |
-
<email/>
|
83 |
<frequency backend_model="adminhtml/system_config_backend_product_alert_cron">every_5min</frequency>
|
84 |
<disabled>0</disabled>
|
85 |
<time>02,00,00</time>
|
@@ -87,9 +75,6 @@
|
|
87 |
</hawksearch_datafeed>
|
88 |
</default>
|
89 |
<crontab>
|
90 |
-
<hawksearch_datafeed>
|
91 |
-
<job_code>hawksearch_datafeed</job_code>
|
92 |
-
</hawksearch_datafeed>
|
93 |
<jobs>
|
94 |
<hawksearch_datafeed>
|
95 |
<run>
|
12 |
<config>
|
13 |
<modules>
|
14 |
<Hawksearch_Datafeed>
|
15 |
+
<version>1.0.3.0</version>
|
16 |
</Hawksearch_Datafeed>
|
17 |
</modules>
|
18 |
<global>
|
20 |
<hawksearch_datafeed>
|
21 |
<class>Hawksearch_Datafeed_Block</class>
|
22 |
</hawksearch_datafeed>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
23 |
</blocks>
|
24 |
<helpers>
|
25 |
<hawksearch_datafeed>
|
57 |
<logging_enabled>1</logging_enabled>
|
58 |
</general>
|
59 |
<feed>
|
|
|
|
|
60 |
<batch_limit>10000</batch_limit>
|
61 |
<image_width>135</image_width>
|
|
|
62 |
<exclude_fields>description,short_description,options_container,gift_message_available,visibility,status,tax_class_id,required_options,msrp_display_actual_price_type,enable_googlecheckout,created_at,updated_at,sku</exclude_fields>
|
63 |
+
<stockstatus>0</stockstatus>
|
64 |
<itemstatus>0</itemstatus>
|
|
|
65 |
<delimiter>tab</delimiter>
|
66 |
<buffer_size>65536</buffer_size>
|
67 |
<output_file_ext>txt</output_file_ext>
|
68 |
<feed_path>var/hawksearch/feeds</feed_path>
|
69 |
</feed>
|
70 |
<cron>
|
|
|
71 |
<frequency backend_model="adminhtml/system_config_backend_product_alert_cron">every_5min</frequency>
|
72 |
<disabled>0</disabled>
|
73 |
<time>02,00,00</time>
|
75 |
</hawksearch_datafeed>
|
76 |
</default>
|
77 |
<crontab>
|
|
|
|
|
|
|
78 |
<jobs>
|
79 |
<hawksearch_datafeed>
|
80 |
<run>
|
app/code/community/Hawksearch/Datafeed/etc/system.xml
CHANGED
@@ -181,15 +181,6 @@
|
|
181 |
<show_in_website>0</show_in_website>
|
182 |
<show_in_store>0</show_in_store>
|
183 |
</optional_htaccess_password>
|
184 |
-
<option_type translate="label">
|
185 |
-
<label>Attribute type</label>
|
186 |
-
<frontend_type>text</frontend_type>
|
187 |
-
<comment>Mode should generally be set to 'eav'</comment>
|
188 |
-
<sort_order>900</sort_order>
|
189 |
-
<show_in_default>1</show_in_default>
|
190 |
-
<show_in_website>0</show_in_website>
|
191 |
-
<show_in_store>0</show_in_store>
|
192 |
-
</option_type>
|
193 |
</fields>
|
194 |
</feed>
|
195 |
<cron translate="label" module="hawksearch_datafeed">
|
181 |
<show_in_website>0</show_in_website>
|
182 |
<show_in_store>0</show_in_store>
|
183 |
</optional_htaccess_password>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
184 |
</fields>
|
185 |
</feed>
|
186 |
<cron translate="label" module="hawksearch_datafeed">
|
app/design/adminhtml/default/default/template/hawksearch/datafeed/clearts/js.phtml
ADDED
@@ -0,0 +1,65 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) 2013 Hawksearch (www.hawksearch.com) - All Rights Reserved
|
4 |
+
*
|
5 |
+
* THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
|
6 |
+
* KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
7 |
+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
8 |
+
* PARTICULAR PURPOSE.
|
9 |
+
*/
|
10 |
+
?>
|
11 |
+
<script type="text/javascript">
|
12 |
+
//<![CDATA[
|
13 |
+
|
14 |
+
var hawkSearchTimestamp = {
|
15 |
+
isInit : false,
|
16 |
+
buttonId : null,
|
17 |
+
init : function() {
|
18 |
+
this.url = '<?php echo $this->getClearUrl() ?>';
|
19 |
+
this.buttonId = '<?php echo $this->getButtonId()?>';
|
20 |
+
this.displayId = "hawksearch_display_msg";
|
21 |
+
this.isInit = true;
|
22 |
+
},
|
23 |
+
clear : function() {
|
24 |
+
var r = confirm("Clearing the timestamp will cause the next feed generation to produce a full result set. Are you sure you want to continue?");
|
25 |
+
if(r != true) {
|
26 |
+
return;
|
27 |
+
}
|
28 |
+
if (!this.isInit) {
|
29 |
+
this.init();
|
30 |
+
}
|
31 |
+
new Ajax.Request(this.url, {
|
32 |
+
onSuccess: function(transport) {
|
33 |
+
var response = transport.responseText.evalJSON();
|
34 |
+
this.displayResults(response);
|
35 |
+
}.bind(this)
|
36 |
+
});
|
37 |
+
},
|
38 |
+
displayResults : function(response) {
|
39 |
+
if(response.error) {
|
40 |
+
alert(response.error);
|
41 |
+
return;
|
42 |
+
}
|
43 |
+
var lastGen = $('hawksearch_lastgen_time');
|
44 |
+
lastGen.innerHTML = response.lastGen;
|
45 |
+
$(this.buttonId).disabled = true;
|
46 |
+
$(this.buttonId).addClassName("disabled");
|
47 |
+
|
48 |
+
/*
|
49 |
+
var responseEl = $(this.displayId);
|
50 |
+
if (responseEl == null) {
|
51 |
+
var responseEl = new Element('p', {id : this.displayId}).addClassName('note');
|
52 |
+
Element.insert($(this.buttonId) , {after: responseEl});
|
53 |
+
}
|
54 |
+
if (response.error) {
|
55 |
+
return responseEl.innerHTML = response.error;
|
56 |
+
}
|
57 |
+
$(this.buttonId).disabled = true;
|
58 |
+
$(this.buttonId).addClassName("disabled");
|
59 |
+
return responseEl.innerHTML = "<?php echo Mage::getModel('hawksearch_datafeed/feed')->getAjaxNotice(); ?>";
|
60 |
+
*/
|
61 |
+
}
|
62 |
+
}
|
63 |
+
|
64 |
+
//]]>
|
65 |
+
</script>
|
app/design/adminhtml/default/default/template/hawksearch/datafeed/generate/js.phtml
ADDED
@@ -0,0 +1,56 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Copyright (c) 2013 Hawksearch (www.hawksearch.com) - All Rights Reserved
|
4 |
+
*
|
5 |
+
* THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
|
6 |
+
* KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
7 |
+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
8 |
+
* PARTICULAR PURPOSE.
|
9 |
+
*/
|
10 |
+
?>
|
11 |
+
<script type="text/javascript">
|
12 |
+
//<![CDATA[
|
13 |
+
|
14 |
+
var hawkSearchFeed = {
|
15 |
+
isInit: false,
|
16 |
+
buttonId: null,
|
17 |
+
init: function () {
|
18 |
+
this.url = '<?php echo $this->getGenerateUrl() ?>';
|
19 |
+
this.buttonId = '<?php echo $this->getButtonId()?>';
|
20 |
+
this.displayId = "hawksearch_display_msg";
|
21 |
+
this.isInit = true;
|
22 |
+
},
|
23 |
+
generateFeed: function () {
|
24 |
+
if (!this.isInit) {
|
25 |
+
this.init();
|
26 |
+
}
|
27 |
+
new Ajax.Request(this.url, {
|
28 |
+
onSuccess: function (transport) {
|
29 |
+
var response = transport.responseText.evalJSON();
|
30 |
+
this.displayResults(response);
|
31 |
+
}.bind(this),
|
32 |
+
onFailure: function (response, rHeader) {
|
33 |
+
alert('there has been an error, status is: ');
|
34 |
+
}.bind(this),
|
35 |
+
onException: function(request, exception) {
|
36 |
+
alert('there has been an XHR exception');
|
37 |
+
}.bind(this)
|
38 |
+
});
|
39 |
+
},
|
40 |
+
displayResults: function (response) {
|
41 |
+
var responseEl = $(this.displayId);
|
42 |
+
if (responseEl == null) {
|
43 |
+
var responseEl = new Element('p', {id: this.displayId}).addClassName('note');
|
44 |
+
Element.insert($(this.buttonId), {after: responseEl});
|
45 |
+
}
|
46 |
+
if (response.error) {
|
47 |
+
return responseEl.innerHTML = response.error;
|
48 |
+
}
|
49 |
+
$(this.buttonId).disabled = true;
|
50 |
+
$(this.buttonId).addClassName("disabled");
|
51 |
+
return responseEl.innerHTML = "<?php echo Mage::getModel('hawksearch_datafeed/feed')->getAjaxNotice(); ?>";
|
52 |
+
}
|
53 |
+
}
|
54 |
+
|
55 |
+
//]]>
|
56 |
+
</script>
|
app/design/adminhtml/default/default/template/hawksearch/{search/sysconfig → datafeed}/generateimagecache/js.phtml
RENAMED
File without changes
|
app/design/adminhtml/default/default/template/hawksearch/search/sysconfig/generate/js.phtml
DELETED
@@ -1,50 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
/**
|
3 |
-
* Copyright (c) 2013 Hawksearch (www.hawksearch.com) - All Rights Reserved
|
4 |
-
*
|
5 |
-
* THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
|
6 |
-
* KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
7 |
-
* IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
8 |
-
* PARTICULAR PURPOSE.
|
9 |
-
*/
|
10 |
-
?>
|
11 |
-
<script type="text/javascript">
|
12 |
-
//<![CDATA[
|
13 |
-
|
14 |
-
var hawkSearchFeed = {
|
15 |
-
isInit : false,
|
16 |
-
buttonId : null,
|
17 |
-
init : function() {
|
18 |
-
this.url = '<?php echo $this->getGenerateUrl() ?>';
|
19 |
-
this.buttonId = '<?php echo $this->getButtonId()?>';
|
20 |
-
this.displayId = "hawksearch_display_msg";
|
21 |
-
this.isInit = true;
|
22 |
-
},
|
23 |
-
generateFeed : function() {
|
24 |
-
if (!this.isInit) {
|
25 |
-
this.init();
|
26 |
-
}
|
27 |
-
new Ajax.Request(this.url, {
|
28 |
-
onSuccess: function(transport) {
|
29 |
-
var response = transport.responseText.evalJSON();
|
30 |
-
this.displayResults(response);
|
31 |
-
}.bind(this)
|
32 |
-
});
|
33 |
-
},
|
34 |
-
displayResults : function(response) {
|
35 |
-
var responseEl = $(this.displayId);
|
36 |
-
if (responseEl == null) {
|
37 |
-
var responseEl = new Element('p', {id : this.displayId}).addClassName('note');
|
38 |
-
Element.insert($(this.buttonId) , {after: responseEl});
|
39 |
-
}
|
40 |
-
if (response.error) {
|
41 |
-
return responseEl.innerHTML = response.error;
|
42 |
-
}
|
43 |
-
$(this.buttonId).disabled = true;
|
44 |
-
$(this.buttonId).addClassName("disabled");
|
45 |
-
return responseEl.innerHTML = "<?php echo Mage::getModel('hawksearch_datafeed/feed')->getAjaxNotice(); ?>";
|
46 |
-
}
|
47 |
-
}
|
48 |
-
|
49 |
-
//]]>
|
50 |
-
</script>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
package.xml
CHANGED
@@ -1,20 +1,18 @@
|
|
1 |
<?xml version="1.0"?>
|
2 |
<package>
|
3 |
<name>HawkSearch_Datafeed</name>
|
4 |
-
<version>1.0.0
|
5 |
<stability>stable</stability>
|
6 |
<license uri="http://opensource.org/licenses/OSL-3.0">Open Software License (OSL)</license>
|
7 |
<channel>community</channel>
|
8 |
<extends/>
|
9 |
<summary>This package generates data feeds in the required format and can be consumed by Hawk Search.</summary>
|
10 |
<description>This package generates data feeds in the required format and can be consumed by Hawk Search.</description>
|
11 |
-
<notes>
|
12 |
-
Should have category generation for attributes file
|
13 |
-
Minor fix for attributes returning int values.</notes>
|
14 |
<authors><author><name>Hawksearch Inc.</name><user>hawksearch</user><email>mmunoz@thanxmedia.com</email></author></authors>
|
15 |
-
<date>
|
16 |
-
<time>14:
|
17 |
-
<contents><target name="magecommunity"><dir name="Hawksearch"><dir name="Datafeed"><dir name="Block"><dir name="System"><dir name="Config"><dir name="Form"><dir name="Field"><file name="Version.php" hash="7f72ce91b67d40e68424454a449f1841"/></dir></dir><file name="Form.php" hash="1f6eaf265d3b8c78d3efd93cf93c7f2d"/><dir name="Frontend"><dir name="Feed"><dir name="Generate"><file name="Js.php" hash="
|
18 |
<compatible/>
|
19 |
<dependencies><required><php><min>5.1.0</min><max>8.1.0</max></php></required></dependencies>
|
20 |
</package>
|
1 |
<?xml version="1.0"?>
|
2 |
<package>
|
3 |
<name>HawkSearch_Datafeed</name>
|
4 |
+
<version>1.0.3.0</version>
|
5 |
<stability>stable</stability>
|
6 |
<license uri="http://opensource.org/licenses/OSL-3.0">Open Software License (OSL)</license>
|
7 |
<channel>community</channel>
|
8 |
<extends/>
|
9 |
<summary>This package generates data feeds in the required format and can be consumed by Hawk Search.</summary>
|
10 |
<description>This package generates data feeds in the required format and can be consumed by Hawk Search.</description>
|
11 |
+
<notes>Added debug logging, category url to hierarchy file.</notes>
|
|
|
|
|
12 |
<authors><author><name>Hawksearch Inc.</name><user>hawksearch</user><email>mmunoz@thanxmedia.com</email></author></authors>
|
13 |
+
<date>2015-02-18</date>
|
14 |
+
<time>14:14:33</time>
|
15 |
+
<contents><target name="magecommunity"><dir name="Hawksearch"><dir name="Datafeed"><dir name="Block"><dir name="System"><dir name="Config"><dir name="Form"><dir name="Field"><file name="Version.php" hash="7f72ce91b67d40e68424454a449f1841"/></dir></dir><file name="Form.php" hash="1f6eaf265d3b8c78d3efd93cf93c7f2d"/><dir name="Frontend"><dir name="Feed"><dir name="Clearts"><file name="Js.php" hash="220b75f831af835d97be401798ec9461"/></dir><dir name="Generate"><file name="Js.php" hash="7e3f96c837b6602759160d4bb92635bf"/></dir><file name="Generate.php" hash="c73b0b2bd965b5c4e4cded455f23baa1"/><dir name="Generateimagecache"><file name="Js.php" hash="25ff246f556d518bcb05198101ec0d7f"/></dir><file name="Generateimagecache.php" hash="05a3585804163326b33d3a46ab7717b5"/><file name="Next.php" hash="92a25b140bc4d0f3b0c7b497fdf0ca6d"/><file name="Timestamp.php" hash="b12e57c577b7c86b346e0221256de97c"/></dir></dir></dir></dir></dir><dir name="Helper"><file name="Data.php" hash="38cddf31605b88ea36cc83fa0d3e1f5f"/><file name="Feed.php" hash="07044195f931f3c59895b3b9b4059607"/><file name="runfeed.php" hash="aa1d25bd6e86ba401a03b0b54885be7e"/></dir><dir name="Model"><file name="Cron.php" hash="ca8d435d3c2f99b09758cb7644a5d141"/><file name="Email.php" hash="f671df12afac28ae10713cd1972bef2c"/><file name="Feed.php" hash="4da148d858cb296920d079765f2481ba"/><dir name="System"><dir name="Config"><dir name="Backend"><file name="Cron.php" hash="2919385264c00276cbf09c105418d5ed"/></dir></dir></dir></dir><dir name="controllers"><file name="SearchController.php" hash="624b4a3ed9baa851174a8708cb15305b"/></dir><dir name="etc"><file name="adminhtml.xml" hash="96daebeddbd749dfe0341818fe2eeabb"/><file name="config.xml" hash="4596283312f96e6e1728eb7a50643762"/><file name="system.xml" hash="3b763bc3073ce575eedb1632efc988a3"/></dir><dir name="sql"><dir name="hawksearch_datafeed_setup"><file name="install-1.0.0.0.php" hash="768e75fd75bbd9532c92859346d78ef2"/></dir></dir></dir></dir></target><target name="magedesign"><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="template"><dir name="hawksearch"><dir name="datafeed"><dir name="clearts"><file name="js.phtml" hash="e277cac474bb3e0d84b47c82c76448ca"/></dir><dir name="generate"><file name="js.phtml" hash="bb03ad1f14206b2e8e5ee228ac0cb6bc"/></dir><dir name="generateimagecache"><file name="js.phtml" hash="aba0594893460ae5763ae243866e7e65"/></dir></dir></dir></dir></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="Hawksearch_Datafeed.xml" hash="06b94625c6b60d1269fe61c4127d2146"/></dir></target></contents>
|
16 |
<compatible/>
|
17 |
<dependencies><required><php><min>5.1.0</min><max>8.1.0</max></php></required></dependencies>
|
18 |
</package>
|